blob: 7b5c47b1ac406f3644e9ff2e280df3fcb87a1340 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhan81e89fe2024-03-20 21:17:09 +000019#include "FakeInputDispatcherPolicy.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhanc5340732024-03-20 22:53:52 +000021#include "FakeWindows.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000022#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080023
Cody Heiner166a5af2023-07-07 12:25:00 -070024#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000025#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070026#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080027#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070029#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070030#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000032#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000033#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080034#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080036#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100037#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070038#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070039#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080041#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080044#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070045#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080046#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080047#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Garfield Tan1c7bc862020-01-28 13:24:04 -080049using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050050using android::gui::FocusRequest;
51using android::gui::TouchOcclusionMode;
52using android::gui::WindowInfo;
53using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080054using android::os::InputEventInjectionResult;
55using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080056
Garfield Tane84e6f92019-08-29 17:28:41 -070057namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080060using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000061using testing::Not;
Siarhei Vishniakou85eb5802024-04-01 11:40:59 -070062using testing::Pointee;
63using testing::UnorderedElementsAre;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070064
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070065namespace {
66
Michael Wrightd02c5b62014-02-10 15:10:22 -080067// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000068static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080069
70// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000071static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080072static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080073
Jeff Brownf086ddb2014-02-11 14:28:48 -080074// An arbitrary display id.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070075constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Linnan Li13bf76a2024-05-05 19:18:02 +080076constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
Jeff Brownf086ddb2014-02-11 14:28:48 -080077
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000078// Ensure common actions are interchangeable between keys and motions for convenience.
79static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
80static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
82static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
83static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
84static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070085static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080086static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070087static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080088static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080089static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080090/**
91 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
92 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
93 * index 0) is the new pointer going down. The same pointer could have been placed at a different
94 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
95 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
96 * pointer id=0 leaves but the pointer id=1 remains.
97 */
98static constexpr int32_t POINTER_0_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100static constexpr int32_t POINTER_1_DOWN =
101 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +0000102static constexpr int32_t POINTER_2_DOWN =
103 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000104static constexpr int32_t POINTER_3_DOWN =
105 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000106static constexpr int32_t POINTER_0_UP =
107 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800108static constexpr int32_t POINTER_1_UP =
109 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000110static constexpr int32_t POINTER_2_UP =
111 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800112
Antonio Kantek15beb512022-06-13 22:35:41 +0000113// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000115static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000116
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000118static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000119
Linnan Li72352222024-04-12 18:55:57 +0800120static constexpr int EXPECTED_WALLPAPER_FLAGS =
Arthur Hungc539dbb2022-12-08 07:45:36 +0000121 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800123using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124
Gang Wang342c9272020-01-13 13:15:04 -0500125/**
126 * Return a DOWN key event with KEYCODE_A.
127 */
128static KeyEvent getTestKeyEvent() {
129 KeyEvent event;
130
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700131 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
132 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
133 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500134 return event;
135}
136
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700137/**
138 * Provide a local override for a flag value. The value is restored when the object of this class
139 * goes out of scope.
140 * This class is not intended to be used directly, because its usage is cumbersome.
141 * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
142 */
143class ScopedFlagOverride {
144public:
145 ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
146 : mInitialValue(read()), mWriteValue(write) {
147 mWriteValue(value);
148 }
149 ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
150
151private:
152 const bool mInitialValue;
153 std::function<void(bool)> mWriteValue;
154};
155
156typedef bool (*readFlagValueFunction)();
157typedef void (*writeFlagValueFunction)(bool);
158
159/**
160 * Use this macro to locally override a flag value.
161 * Example usage:
162 * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
163 * Note: this works by creating a local variable in your current scope. Don't call this twice for
164 * the same flag, because the variable names will clash!
165 */
166#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
167 readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
168 writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
169 ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
170
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172
Michael Wrightd02c5b62014-02-10 15:10:22 -0800173// --- InputDispatcherTest ---
174
175class InputDispatcherTest : public testing::Test {
176protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000177 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700178 std::unique_ptr<InputDispatcher> mDispatcher;
Prabir Pradhanc5340732024-03-20 22:53:52 +0000179 std::shared_ptr<VerifyingTrace> mVerifyingTrace;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 void SetUp() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000182 mVerifyingTrace = std::make_shared<VerifyingTrace>();
183 FakeWindowHandle::sOnEventReceivedCallback = [this](const auto& _1, const auto& _2) {
184 handleEventReceivedByWindow(_1, _2);
185 };
186
Prabir Pradhana41d2442023-04-20 21:30:40 +0000187 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000188 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
189 std::make_unique<FakeInputTracingBackend>(
Prabir Pradhanc5340732024-03-20 22:53:52 +0000190 mVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700191
Harry Cutts101ee9b2023-07-06 18:04:14 +0000192 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000193 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700194 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195 }
196
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000197 void TearDown() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000198 ASSERT_NO_FATAL_FAILURE(mVerifyingTrace->verifyExpectedEventsTraced());
199 FakeWindowHandle::sOnEventReceivedCallback = nullptr;
200
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700201 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000202 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700203 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205
Prabir Pradhanc5340732024-03-20 22:53:52 +0000206 void handleEventReceivedByWindow(const std::unique_ptr<InputEvent>& event,
207 const gui::WindowInfo& info) {
208 if (!event) {
209 return;
210 }
211
212 switch (event->getType()) {
213 case InputEventType::KEY: {
214 mVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), info.id);
215 break;
216 }
217 case InputEventType::MOTION: {
218 mVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
219 info.id);
220 break;
221 }
222 default:
223 break;
224 }
225 }
226
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700227 /**
228 * Used for debugging when writing the test
229 */
230 void dumpDispatcherState() {
231 std::string dump;
232 mDispatcher->dump(dump);
233 std::stringstream ss(dump);
234 std::string to;
235
236 while (std::getline(ss, to, '\n')) {
237 ALOGE("%s", to.c_str());
238 }
239 }
Vishnu Nair958da932020-08-21 17:12:37 -0700240
Chavi Weingarten847e8512023-03-29 00:26:09 +0000241 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700242 FocusRequest request;
243 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000244 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700245 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Linnan Li13bf76a2024-05-05 19:18:02 +0800246 request.displayId = window->getInfo()->displayId.val();
Vishnu Nair958da932020-08-21 17:12:37 -0700247 mDispatcher->setFocusedWindow(request);
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249};
250
Michael Wrightd02c5b62014-02-10 15:10:22 -0800251TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
252 KeyEvent event;
253
254 // Rejects undefined key actions.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700255 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
256 ui::LogicalDisplayId::INVALID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000257 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600258 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800259 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000260 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000261 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 << "Should reject key events with undefined action.";
263
264 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700265 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
266 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0,
267 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800268 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000269 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000270 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 << "Should reject key events with ACTION_MULTIPLE.";
272}
273
274TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
275 MotionEvent event;
276 PointerProperties pointerProperties[MAX_POINTERS + 1];
277 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800278 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279 pointerProperties[i].clear();
280 pointerProperties[i].id = i;
281 pointerCoords[i].clear();
282 }
283
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800284 // Some constants commonly used below
285 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
286 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
287 constexpr int32_t metaState = AMETA_NONE;
288 constexpr MotionClassification classification = MotionClassification::NONE;
289
chaviw9eaa22c2020-07-01 16:21:27 -0700290 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800292 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000293 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700294 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700295 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
296 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000297 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000299 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000300 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 << "Should reject motion events with undefined action.";
302
303 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800304 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800305 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
306 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
307 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
308 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000309 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800310 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000311 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000312 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 << "Should reject motion events with pointer down index too large.";
314
Garfield Tanfbe732e2020-01-24 11:26:14 -0800315 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700316 AMOTION_EVENT_ACTION_POINTER_DOWN |
317 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700318 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
319 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700320 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000321 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800322 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000323 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000324 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800325 << "Should reject motion events with pointer down index too small.";
326
327 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800328 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800329 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
330 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
331 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
332 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000333 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800334 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000335 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000336 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 << "Should reject motion events with pointer up index too large.";
338
Garfield Tanfbe732e2020-01-24 11:26:14 -0800339 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700340 AMOTION_EVENT_ACTION_POINTER_UP |
341 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700342 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
343 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700344 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000345 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000347 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000348 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 << "Should reject motion events with pointer up index too small.";
350
351 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800352 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
353 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700354 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700355 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
356 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000357 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800358 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000359 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000360 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361 << "Should reject motion events with 0 pointers.";
362
Garfield Tanfbe732e2020-01-24 11:26:14 -0800363 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
364 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700365 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700366 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
367 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000368 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800369 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000370 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000371 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800372 << "Should reject motion events with more than MAX_POINTERS pointers.";
373
374 // Rejects motion events with invalid pointer ids.
375 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800376 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
377 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700378 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700379 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
380 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000381 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800382 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000383 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000384 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385 << "Should reject motion events with pointer ids less than 0.";
386
387 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800388 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
389 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700390 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700391 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
392 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000393 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800394 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000395 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000396 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800397 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
398
399 // Rejects motion events with duplicate pointer ids.
400 pointerProperties[0].id = 1;
401 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800402 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
403 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700404 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700405 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
406 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000407 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000409 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000410 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411 << "Should reject motion events with duplicate pointer ids.";
412}
413
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800414TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000415 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
416 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000417 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000418 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800419
420 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
421 args.policyFlags |= POLICY_FLAG_TRUSTED;
422 mFakePolicy->assertNotifySwitchWasCalled(args);
423}
424
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700425namespace {
426
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700427static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700428
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000429class FakeMonitorReceiver {
430public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800431 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
432 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700433 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000434
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700435 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000436
Linnan Li13bf76a2024-05-05 19:18:02 +0800437 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700438 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
439 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000440 }
441
442 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800443 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
444 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000445 }
446
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700447 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000448
Linnan Li13bf76a2024-05-05 19:18:02 +0800449 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700450 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
451 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000452 }
453
Linnan Li13bf76a2024-05-05 19:18:02 +0800454 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700455 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
456 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000457 }
458
Linnan Li13bf76a2024-05-05 19:18:02 +0800459 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
461 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000462 }
463
Linnan Li13bf76a2024-05-05 19:18:02 +0800464 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000466 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
467 WithDisplayId(expectedDisplayId),
468 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
469 }
470
471 void consumeMotionPointerDown(int32_t pointerIdx) {
472 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
473 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700474 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700475 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000476 }
477
478 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700479 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000480 }
481
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800482 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000483
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800484 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000485
486private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700487 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000488};
489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800490static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700491 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700492 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800493 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800494 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000495 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000496 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800497 KeyEvent event;
498 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
499
500 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800501 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000502 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
503 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800504
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800505 if (!allowKeyRepeat) {
506 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
507 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800508 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700509 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800510}
511
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700512static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
513 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700514 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
515 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
516 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700517 if (result != InputEventInjectionResult::TIMED_OUT) {
518 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
519 }
520}
521
Linnan Li13bf76a2024-05-05 19:18:02 +0800522static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700523 InputDispatcher& dispatcher,
524 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000525 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700526}
527
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800528// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
529// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
530// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800531static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700532 InputDispatcher& dispatcher,
533 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000534 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800535 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000536 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800537}
538
Linnan Li13bf76a2024-05-05 19:18:02 +0800539static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700540 InputDispatcher& dispatcher,
541 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000542 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700543}
544
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800545static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700546 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700547 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000548 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000549 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700550 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
551 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700552}
553
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800554static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800555 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700556 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700557 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700558 AMOTION_EVENT_INVALID_CURSOR_POSITION},
559 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800560 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000561 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000562 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700563 MotionEventBuilder motionBuilder =
564 MotionEventBuilder(action, source)
565 .displayId(displayId)
566 .eventTime(eventTime)
567 .rawXCursorPosition(cursorPosition.x)
568 .rawYCursorPosition(cursorPosition.y)
569 .pointer(
570 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
571 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
572 motionBuilder.downTime(eventTime);
573 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800574
575 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700576 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
577 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800578}
579
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700580static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800581 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700582 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700583 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700584}
585
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700586static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800587 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800588 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700589 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000590}
591
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700592static NotifyKeyArgs generateKeyArgs(
593 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800594 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
595 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000596 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
597 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
598 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800599
600 return args;
601}
602
Prabir Pradhan678438e2023-04-13 19:32:51 +0000603[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800604 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000605 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800606 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700607 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
608 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
609 }
610
chaviwd1c23182019-12-20 18:44:56 -0800611 PointerProperties pointerProperties[pointerCount];
612 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800613
chaviwd1c23182019-12-20 18:44:56 -0800614 for (size_t i = 0; i < pointerCount; i++) {
615 pointerProperties[i].clear();
616 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700617 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800618
chaviwd1c23182019-12-20 18:44:56 -0800619 pointerCoords[i].clear();
620 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
621 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
622 }
Jackal Guof9696682018-10-05 12:23:23 +0800623
624 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
625 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000626 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
627 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
628 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800629 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000630 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700631 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000632 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800633
634 return args;
635}
636
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800637static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
638 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
639}
640
Linnan Li13bf76a2024-05-05 19:18:02 +0800641static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
642 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800643 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
644}
645
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000646static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
647 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000648 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
649 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800650}
651
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700652} // namespace
653
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800654/**
655 * When a window unexpectedly disposes of its input channel, policy should be notified about the
656 * broken channel.
657 */
658TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
661 "Window that breaks its input channel",
662 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800663
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700664 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800665
666 // Window closes its channel, but the window remains.
667 window->destroyReceiver();
668 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
669}
670
Arthur Hungb92218b2018-08-14 12:00:21 +0800671TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700673 sp<FakeWindowHandle> window =
674 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
675 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800676
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700679 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
680 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800682
683 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700684 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800685}
686
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800687using InputDispatcherDeathTest = InputDispatcherTest;
688
689/**
690 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
691 * should crash.
692 */
693TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
694 testing::GTEST_FLAG(death_test_style) = "threadsafe";
695 ScopedSilentDeath _silentDeath;
696
697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700698 sp<FakeWindowHandle> window =
699 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
700 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800701 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
702 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
703 "Incorrect WindowInfosUpdate provided");
704}
705
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700706TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700708 sp<FakeWindowHandle> window =
709 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
710 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700711
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700713 // Inject a MotionEvent to an unknown display.
714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
716 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
718
719 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700720 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700721}
722
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700723/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700724 * Calling onWindowInfosChanged once should not cause any issues.
725 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700726 * called twice.
727 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800728TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700730 sp<FakeWindowHandle> window =
731 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
732 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700733 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700734
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700735 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
738 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700740
741 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700742 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700743}
744
745/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700746 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700747 */
748TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700750 sp<FakeWindowHandle> window =
751 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
752 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700753 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
756 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
759 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700761
762 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700763 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700764}
765
Arthur Hungb92218b2018-08-14 12:00:21 +0800766// The foreground window should receive the first touch down event.
767TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700769 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
770 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000771 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700772 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
773 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700775 mDispatcher->onWindowInfosChanged(
776 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
779 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800781
782 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700783 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800784 windowSecond->assertNoEvents();
785}
786
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000787/**
788 * Two windows: A top window, and a wallpaper behind the window.
789 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
790 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800791 * 1. foregroundWindow <-- dup touch to wallpaper
792 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000793 */
794TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
796 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700797 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
798 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800799 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000800 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700801 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
802 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800803 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000804
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700805 mDispatcher->onWindowInfosChanged(
806 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800808 injectMotionEvent(*mDispatcher,
809 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
810 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
811 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
813
814 // Both foreground window and its wallpaper should receive the touch down
815 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700816 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000817
818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800819 injectMotionEvent(*mDispatcher,
820 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
821 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
822 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
824
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800825 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700826 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000827
828 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700829 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000830 foregroundWindow->consumeMotionCancel();
831 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700832 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000833}
834
835/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800836 * Two fingers down on the window, and lift off the first finger.
837 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
838 * contains a single pointer.
839 */
840TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
843 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800844
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700845 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
848 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
849 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800850 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000851 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
852 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
853 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
854 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800855 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000856 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
857 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
858 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
859 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800860 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
861 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
862 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
863
864 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700865 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800866 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
867 window->consumeMotionEvent(
868 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
869}
870
871/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800872 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
873 * with the following differences:
874 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
875 * clean up the connection.
876 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
877 * Ensure that there's no crash in the dispatcher.
878 */
879TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
881 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700882 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
883 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800884 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800885 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700886 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
887 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800888 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800889
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700890 mDispatcher->onWindowInfosChanged(
891 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
894 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
896
897 // Both foreground window and its wallpaper should receive the touch down
898 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700899 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800900
901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700902 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700903 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
905
906 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700907 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800908
909 // Wallpaper closes its channel, but the window remains.
910 wallpaperWindow->destroyReceiver();
911 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
912
913 // Now the foreground window goes away, but the wallpaper stays, even though its channel
914 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700915 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800916 foregroundWindow->consumeMotionCancel();
917}
918
Linnan Li72352222024-04-12 18:55:57 +0800919/**
920 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
921 * down event to the left window. Device B sends a down event to the right window. Next, the right
922 * window disappears. Both the right window and its wallpaper window should receive cancel event.
923 * The left window and its wallpaper window should not receive any events.
924 */
925TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
927 sp<FakeWindowHandle> leftForegroundWindow =
928 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700929 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800930 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
931 leftForegroundWindow->setDupTouchToWallpaper(true);
932 sp<FakeWindowHandle> leftWallpaperWindow =
933 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700934 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800935 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
936 leftWallpaperWindow->setIsWallpaper(true);
937
938 sp<FakeWindowHandle> rightForegroundWindow =
939 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700940 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800941 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
942 rightForegroundWindow->setDupTouchToWallpaper(true);
943 sp<FakeWindowHandle> rightWallpaperWindow =
944 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700945 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800946 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
947 rightWallpaperWindow->setIsWallpaper(true);
948
949 mDispatcher->onWindowInfosChanged(
950 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
951 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
952 {},
953 0,
954 0});
955
956 const DeviceId deviceA = 9;
957 const DeviceId deviceB = 3;
958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
959 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
960 .deviceId(deviceA)
961 .build());
962 leftForegroundWindow->consumeMotionEvent(
963 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
964 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
965 WithDeviceId(deviceA),
966 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
967
968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
969 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
970 .deviceId(deviceB)
971 .build());
972 rightForegroundWindow->consumeMotionEvent(
973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
974 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
975 WithDeviceId(deviceB),
976 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
977
978 // Now right foreground window disappears, but right wallpaper window remains.
979 mDispatcher->onWindowInfosChanged(
980 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
981 *rightWallpaperWindow->getInfo()},
982 {},
983 0,
984 0});
985
986 // Left foreground window and left wallpaper window still exist, and should not receive any
987 // events.
988 leftForegroundWindow->assertNoEvents();
989 leftWallpaperWindow->assertNoEvents();
990 // Since right foreground window disappeared, right wallpaper window and right foreground window
991 // should receive cancel events.
992 rightForegroundWindow->consumeMotionEvent(
993 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
994 rightWallpaperWindow->consumeMotionEvent(
995 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
996 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
997}
998
999/**
1000 * Three windows arranged horizontally and without any overlap. Every window has a
1001 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1002 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1003 * Next, device B sends move event to the right window. Touch for device B should slip from the
1004 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1005 * The middle window and its wallpaper window should receive a cancel event. The left window should
1006 * not receive any events. If device B continues to report events, the right window and its
1007 * wallpaper window should receive remaining events.
1008 */
1009TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1011 sp<FakeWindowHandle> leftForegroundWindow =
1012 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001013 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001014 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1015 leftForegroundWindow->setDupTouchToWallpaper(true);
1016 sp<FakeWindowHandle> leftWallpaperWindow =
1017 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001018 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001019 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1020 leftWallpaperWindow->setIsWallpaper(true);
1021
1022 sp<FakeWindowHandle> middleForegroundWindow =
1023 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001024 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001025 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1026 middleForegroundWindow->setDupTouchToWallpaper(true);
1027 middleForegroundWindow->setSlippery(true);
1028 sp<FakeWindowHandle> middleWallpaperWindow =
1029 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001030 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001031 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1032 middleWallpaperWindow->setIsWallpaper(true);
1033
1034 sp<FakeWindowHandle> rightForegroundWindow =
1035 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001036 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001037 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1038 rightForegroundWindow->setDupTouchToWallpaper(true);
1039 sp<FakeWindowHandle> rightWallpaperWindow =
1040 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001041 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001042 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1043 rightWallpaperWindow->setIsWallpaper(true);
1044
1045 mDispatcher->onWindowInfosChanged(
1046 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1047 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1048 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1049 {},
1050 0,
1051 0});
1052
1053 const DeviceId deviceA = 9;
1054 const DeviceId deviceB = 3;
1055 // Device A sends a DOWN event to the left window
1056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1057 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1058 .deviceId(deviceA)
1059 .build());
1060 leftForegroundWindow->consumeMotionEvent(
1061 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1062 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1063 WithDeviceId(deviceA),
1064 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1065 // Device B sends a DOWN event to the middle window
1066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1067 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1068 .deviceId(deviceB)
1069 .build());
1070 middleForegroundWindow->consumeMotionEvent(
1071 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1072 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1073 WithDeviceId(deviceB),
1074 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1075 // Move the events of device B to the top of the right window.
1076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1077 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1078 .deviceId(deviceB)
1079 .build());
1080 middleForegroundWindow->consumeMotionEvent(
1081 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1082 middleWallpaperWindow->consumeMotionEvent(
1083 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1084 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1085 rightForegroundWindow->consumeMotionEvent(
1086 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1087 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1088 WithDeviceId(deviceB),
1089 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1090 // Make sure the window on the right can receive the remaining events.
1091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1092 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1093 .deviceId(deviceB)
1094 .build());
1095 leftForegroundWindow->assertNoEvents();
1096 leftWallpaperWindow->assertNoEvents();
1097 middleForegroundWindow->assertNoEvents();
1098 middleWallpaperWindow->assertNoEvents();
1099 rightForegroundWindow->consumeMotionEvent(
1100 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1101 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1102 WithDeviceId(deviceB),
1103 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1104}
1105
1106/**
1107 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1108 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1109 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1110 * event to the middle window and then touch is transferred from the middle window to the right
1111 * window. The right window and its wallpaper window should receive a down event. The middle window
1112 * and its wallpaper window should receive a cancel event. The left window should not receive any
1113 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1114 */
1115TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1117 sp<FakeWindowHandle> leftForegroundWindow =
1118 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001119 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001120 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1121 leftForegroundWindow->setDupTouchToWallpaper(true);
1122 sp<FakeWindowHandle> leftWallpaperWindow =
1123 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001124 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001125 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1126 leftWallpaperWindow->setIsWallpaper(true);
1127
1128 sp<FakeWindowHandle> middleForegroundWindow =
1129 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001130 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001131 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1132 middleForegroundWindow->setDupTouchToWallpaper(true);
1133 sp<FakeWindowHandle> middleWallpaperWindow =
1134 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001135 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001136 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1137 middleWallpaperWindow->setIsWallpaper(true);
1138
1139 sp<FakeWindowHandle> rightForegroundWindow =
1140 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001141 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001142 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1143 rightForegroundWindow->setDupTouchToWallpaper(true);
1144 sp<FakeWindowHandle> rightWallpaperWindow =
1145 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001146 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001147 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1148 rightWallpaperWindow->setIsWallpaper(true);
1149
1150 mDispatcher->onWindowInfosChanged(
1151 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1152 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1153 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1154 {},
1155 0,
1156 0});
1157
1158 const DeviceId deviceA = 9;
1159 const DeviceId deviceB = 3;
1160 // Device A touch down on the left window
1161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1162 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1163 .deviceId(deviceA)
1164 .build());
1165 leftForegroundWindow->consumeMotionEvent(
1166 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1167 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1168 WithDeviceId(deviceA),
1169 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1170 // Device B touch down on the middle window
1171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1172 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1173 .deviceId(deviceB)
1174 .build());
1175 middleForegroundWindow->consumeMotionEvent(
1176 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1177 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1178 WithDeviceId(deviceB),
1179 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1180
1181 // Transfer touch from the middle window to the right window.
1182 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1183 rightForegroundWindow->getToken()));
1184
1185 middleForegroundWindow->consumeMotionEvent(
1186 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1187 middleWallpaperWindow->consumeMotionEvent(
1188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1189 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1190 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1191 WithDeviceId(deviceB),
1192 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1193 rightWallpaperWindow->consumeMotionEvent(
1194 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1195 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1196
1197 // Make sure the right window can receive the remaining events.
1198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1199 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1200 .deviceId(deviceB)
1201 .build());
1202 leftForegroundWindow->assertNoEvents();
1203 leftWallpaperWindow->assertNoEvents();
1204 middleForegroundWindow->assertNoEvents();
1205 middleWallpaperWindow->assertNoEvents();
1206 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1207 WithDeviceId(deviceB),
1208 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1209 rightWallpaperWindow->consumeMotionEvent(
1210 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1211 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1212}
1213
Arthur Hungc539dbb2022-12-08 07:45:36 +00001214class ShouldSplitTouchFixture : public InputDispatcherTest,
1215 public ::testing::WithParamInterface<bool> {};
1216INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1217 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001218/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001219 * A single window that receives touch (on top), and a wallpaper window underneath it.
1220 * The top window gets a multitouch gesture.
1221 * Ensure that wallpaper gets the same gesture.
1222 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001223TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001225 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001226 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1227 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001228 foregroundWindow->setDupTouchToWallpaper(true);
1229 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001230
1231 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001232 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1233 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001234 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001235
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001236 mDispatcher->onWindowInfosChanged(
1237 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001238
1239 // Touch down on top window
1240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001241 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1242 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1244
1245 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001246 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001247 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001248
1249 // Second finger down on the top window
1250 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001251 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001252 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001253 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1254 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001255 .build();
1256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001257 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001258 InputEventInjectionSync::WAIT_FOR_RESULT))
1259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001260 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001261 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001262 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001263
1264 const MotionEvent secondFingerUpEvent =
1265 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001266 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001267 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001268 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1269 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001270 .build();
1271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001272 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001273 InputEventInjectionSync::WAIT_FOR_RESULT))
1274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001275 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1276 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1277 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1278 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1279 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001280
1281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001283 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1284 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001285 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001286 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001287 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001288 .x(100)
1289 .y(100))
1290 .build(),
1291 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001293 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1294 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001295}
1296
1297/**
1298 * Two windows: a window on the left and window on the right.
1299 * A third window, wallpaper, is behind both windows, and spans both top windows.
1300 * The first touch down goes to the left window. A second pointer touches down on the right window.
1301 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1302 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1303 * ACTION_POINTER_DOWN(1).
1304 */
1305TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001307 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1308 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001309 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001310 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001311
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001312 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1313 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001314 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001315 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001316
1317 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001318 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1319 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001320 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001321 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001322
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001323 mDispatcher->onWindowInfosChanged(
1324 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1325 {},
1326 0,
1327 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001328
1329 // Touch down on left window
1330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001331 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1332 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1334
1335 // Both foreground window and its wallpaper should receive the touch down
1336 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001337 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001338
1339 // Second finger down on the right window
1340 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001341 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001342 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001343 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1344 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001345 .build();
1346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001347 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001348 InputEventInjectionSync::WAIT_FOR_RESULT))
1349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1350
1351 leftWindow->consumeMotionMove();
1352 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001353 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1354 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001355 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001356
1357 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001358 mDispatcher->onWindowInfosChanged(
1359 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001360 leftWindow->consumeMotionCancel();
1361 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001362 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001363
1364 // The pointer that's still down on the right window moves, and goes to the right window only.
1365 // As far as the dispatcher's concerned though, both pointers are still present.
1366 const MotionEvent secondFingerMoveEvent =
1367 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1368 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001369 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1370 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001371 .build();
1372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001373 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001374 InputEventInjectionSync::WAIT_FOR_RESULT));
1375 rightWindow->consumeMotionMove();
1376
1377 leftWindow->assertNoEvents();
1378 rightWindow->assertNoEvents();
1379 wallpaperWindow->assertNoEvents();
1380}
1381
Arthur Hungc539dbb2022-12-08 07:45:36 +00001382/**
1383 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1384 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1385 * The right window should receive ACTION_DOWN.
1386 */
1387TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001389 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1390 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001391 leftWindow->setFrame(Rect(0, 0, 200, 200));
1392 leftWindow->setDupTouchToWallpaper(true);
1393 leftWindow->setSlippery(true);
1394
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001395 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1396 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001397 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001398
1399 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001400 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1401 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001402 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001403
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001404 mDispatcher->onWindowInfosChanged(
1405 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1406 {},
1407 0,
1408 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001409
Arthur Hungc539dbb2022-12-08 07:45:36 +00001410 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001412 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1413 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001415
1416 // Both foreground window and its wallpaper should receive the touch down
1417 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001418 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001419
Arthur Hungc539dbb2022-12-08 07:45:36 +00001420 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001422 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001423 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1425
Arthur Hungc539dbb2022-12-08 07:45:36 +00001426 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001427 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1428 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001429}
1430
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001431/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001432 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1433 * interactive, it might stop sending this flag.
1434 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1435 * to have a consistent input stream.
1436 *
1437 * Test procedure:
1438 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1439 * DOWN (new gesture).
1440 *
1441 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1442 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1443 *
1444 * We technically just need a single window here, but we are using two windows (spy on top and a
1445 * regular window below) to emulate the actual situation where it happens on the device.
1446 */
1447TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001449 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1450 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001451 spyWindow->setFrame(Rect(0, 0, 200, 200));
1452 spyWindow->setTrustedOverlay(true);
1453 spyWindow->setSpy(true);
1454
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001455 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1456 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001457 window->setFrame(Rect(0, 0, 200, 200));
1458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001459 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001460 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001461
1462 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001463 mDispatcher->notifyMotion(
1464 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1465 .deviceId(touchDeviceId)
1466 .policyFlags(DEFAULT_POLICY_FLAGS)
1467 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1468 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001469
Prabir Pradhan678438e2023-04-13 19:32:51 +00001470 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1471 .deviceId(touchDeviceId)
1472 .policyFlags(DEFAULT_POLICY_FLAGS)
1473 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1474 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1475 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001476 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1477 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1478 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1479 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1480
1481 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001482 mDispatcher->notifyMotion(
1483 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1484 .deviceId(touchDeviceId)
1485 .policyFlags(0)
1486 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1487 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1488 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001489 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1490 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1491
1492 // We don't need to reset the device to reproduce the issue, but the reset event typically
1493 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001494 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001495
1496 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001497 mDispatcher->notifyMotion(
1498 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1499 .deviceId(touchDeviceId)
1500 .policyFlags(DEFAULT_POLICY_FLAGS)
1501 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1502 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001503 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1504 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1505
1506 // No more events
1507 spyWindow->assertNoEvents();
1508 window->assertNoEvents();
1509}
1510
1511/**
Linnan Li907ae732023-09-05 17:14:21 +08001512 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1513 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1514 * interactive, it might stop sending this flag.
1515 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1516 * the consistency of the hover event in this case.
1517 *
1518 * Test procedure:
1519 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1520 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1521 *
1522 * We expect to receive two full streams of hover events.
1523 */
1524TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1526
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1528 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001529 window->setFrame(Rect(0, 0, 300, 300));
1530
1531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1532
1533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1534 .policyFlags(DEFAULT_POLICY_FLAGS)
1535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1536 .build());
1537 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1538
1539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1540 .policyFlags(DEFAULT_POLICY_FLAGS)
1541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1542 .build());
1543 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1544
1545 // Send hover exit without the default policy flags.
1546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1547 .policyFlags(0)
1548 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1549 .build());
1550
1551 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1552
1553 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1554 // right event.
1555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1556 .policyFlags(DEFAULT_POLICY_FLAGS)
1557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1558 .build());
1559 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1560
1561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1562 .policyFlags(DEFAULT_POLICY_FLAGS)
1563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1564 .build());
1565 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1566
1567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1568 .policyFlags(DEFAULT_POLICY_FLAGS)
1569 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1570 .build());
1571 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1572}
1573
1574/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001575 * Two windows: a window on the left and a window on the right.
1576 * Mouse is hovered from the right window into the left window.
1577 * Next, we tap on the left window, where the cursor was last seen.
1578 * The second tap is done onto the right window.
1579 * The mouse and tap are from two different devices.
1580 * We technically don't need to set the downtime / eventtime for these events, but setting these
1581 * explicitly helps during debugging.
1582 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1583 * In the buggy implementation, a tap on the right window would cause a crash.
1584 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001585TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1586 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1587
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001589 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1590 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001591 leftWindow->setFrame(Rect(0, 0, 200, 200));
1592
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001593 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1594 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001595 rightWindow->setFrame(Rect(200, 0, 400, 200));
1596
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001597 mDispatcher->onWindowInfosChanged(
1598 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001599 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1600 // stale.
1601 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1602 const int32_t mouseDeviceId = 6;
1603 const int32_t touchDeviceId = 4;
1604 // Move the cursor from right
1605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001606 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001607 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1608 AINPUT_SOURCE_MOUSE)
1609 .deviceId(mouseDeviceId)
1610 .downTime(baseTime + 10)
1611 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001612 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001613 .build()));
1614 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1615
1616 // .. to the left window
1617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001619 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1620 AINPUT_SOURCE_MOUSE)
1621 .deviceId(mouseDeviceId)
1622 .downTime(baseTime + 10)
1623 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001624 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001625 .build()));
1626 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1628 // Now tap the left window
1629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001630 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001631 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1632 AINPUT_SOURCE_TOUCHSCREEN)
1633 .deviceId(touchDeviceId)
1634 .downTime(baseTime + 40)
1635 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001636 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001637 .build()));
1638 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1639 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1640
1641 // release tap
1642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001643 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001644 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1645 AINPUT_SOURCE_TOUCHSCREEN)
1646 .deviceId(touchDeviceId)
1647 .downTime(baseTime + 40)
1648 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001649 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001650 .build()));
1651 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1652
1653 // Tap the window on the right
1654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001655 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001656 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1657 AINPUT_SOURCE_TOUCHSCREEN)
1658 .deviceId(touchDeviceId)
1659 .downTime(baseTime + 60)
1660 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001661 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001662 .build()));
1663 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1664
1665 // release tap
1666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001667 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001668 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1669 AINPUT_SOURCE_TOUCHSCREEN)
1670 .deviceId(touchDeviceId)
1671 .downTime(baseTime + 60)
1672 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001673 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001674 .build()));
1675 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1676
1677 // No more events
1678 leftWindow->assertNoEvents();
1679 rightWindow->assertNoEvents();
1680}
1681
1682/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001683 * Two windows: a window on the left and a window on the right.
1684 * Mouse is hovered from the right window into the left window.
1685 * Next, we tap on the left window, where the cursor was last seen.
1686 * The second tap is done onto the right window.
1687 * The mouse and tap are from two different devices.
1688 * We technically don't need to set the downtime / eventtime for these events, but setting these
1689 * explicitly helps during debugging.
1690 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1691 * In the buggy implementation, a tap on the right window would cause a crash.
1692 */
1693TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1694 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1695
1696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001697 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1698 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001699 leftWindow->setFrame(Rect(0, 0, 200, 200));
1700
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001701 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1702 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001703 rightWindow->setFrame(Rect(200, 0, 400, 200));
1704
1705 mDispatcher->onWindowInfosChanged(
1706 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1707 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1708 // stale.
1709 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1710 const int32_t mouseDeviceId = 6;
1711 const int32_t touchDeviceId = 4;
1712 // Move the cursor from right
1713 mDispatcher->notifyMotion(
1714 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1715 .deviceId(mouseDeviceId)
1716 .downTime(baseTime + 10)
1717 .eventTime(baseTime + 20)
1718 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1719 .build());
1720 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1721
1722 // .. to the left window
1723 mDispatcher->notifyMotion(
1724 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1725 .deviceId(mouseDeviceId)
1726 .downTime(baseTime + 10)
1727 .eventTime(baseTime + 30)
1728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1729 .build());
1730 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1731 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1732 // Now tap the left window
1733 mDispatcher->notifyMotion(
1734 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1735 .deviceId(touchDeviceId)
1736 .downTime(baseTime + 40)
1737 .eventTime(baseTime + 40)
1738 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1739 .build());
1740 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1741
1742 // release tap
1743 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1744 .deviceId(touchDeviceId)
1745 .downTime(baseTime + 40)
1746 .eventTime(baseTime + 50)
1747 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1748 .build());
1749 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1750
1751 // Tap the window on the right
1752 mDispatcher->notifyMotion(
1753 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1754 .deviceId(touchDeviceId)
1755 .downTime(baseTime + 60)
1756 .eventTime(baseTime + 60)
1757 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1758 .build());
1759 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1760
1761 // release tap
1762 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1763 .deviceId(touchDeviceId)
1764 .downTime(baseTime + 60)
1765 .eventTime(baseTime + 70)
1766 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1767 .build());
1768 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1769
1770 // No more events
1771 leftWindow->assertNoEvents();
1772 rightWindow->assertNoEvents();
1773}
1774
1775/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001776 * Start hovering in a window. While this hover is still active, make another window appear on top.
1777 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1778 * While the top window is present, the hovering is stopped.
1779 * Later, hovering gets resumed again.
1780 * Ensure that new hover gesture is handled correctly.
1781 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1782 * to the window that's currently being hovered over.
1783 */
1784TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1787 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001788 window->setFrame(Rect(0, 0, 200, 200));
1789
1790 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001792
1793 // Start hovering in the window
1794 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1796 .build());
1797 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1798
1799 // Now, an obscuring window appears!
1800 sp<FakeWindowHandle> obscuringWindow =
1801 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001802 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001803 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001804 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1805 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1806 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1807 obscuringWindow->setNoInputChannel(true);
1808 obscuringWindow->setFocusable(false);
1809 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001810 mDispatcher->onWindowInfosChanged(
1811 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001812
1813 // While this new obscuring window is present, the hovering is stopped
1814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1815 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1816 .build());
1817 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1818
1819 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001821
1822 // And a new hover gesture starts.
1823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1825 .build());
1826 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1827}
1828
1829/**
1830 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1831 * the obscuring window.
1832 */
1833TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001835 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1836 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001837 window->setFrame(Rect(0, 0, 200, 200));
1838
1839 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001841
1842 // Start hovering in the window
1843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1845 .build());
1846 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1847
1848 // Now, an obscuring window appears!
1849 sp<FakeWindowHandle> obscuringWindow =
1850 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001851 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001852 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001853 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1854 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1855 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1856 obscuringWindow->setNoInputChannel(true);
1857 obscuringWindow->setFocusable(false);
1858 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001859 mDispatcher->onWindowInfosChanged(
1860 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001861
1862 // While this new obscuring window is present, the hovering continues. The event can't go to the
1863 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1864 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1865 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1866 .build());
1867 obscuringWindow->assertNoEvents();
1868 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1869
1870 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001872
1873 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1874 // so it should generate a HOVER_ENTER
1875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1876 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1877 .build());
1878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1879
1880 // Now the MOVE should be getting dispatched normally
1881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1882 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1883 .build());
1884 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1885}
1886
1887/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001888 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1889 * events are delivered to the window.
1890 */
1891TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001893 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1894 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001895 window->setFrame(Rect(0, 0, 200, 200));
1896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1897
1898 // Start hovering in the window
1899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1901 .build());
1902 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1903
1904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1906 .build());
1907 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1908
1909 // Scroll with the mouse
1910 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1912 .build());
1913 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1914}
1915
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -07001916/**
1917 * Two windows: a trusted overlay and a regular window underneath. Both windows are visible.
1918 * Mouse is hovered, and the hover event should only go to the overlay.
1919 * However, next, the touchable region of the trusted overlay shrinks. The mouse position hasn't
1920 * changed, but the cursor would now end up hovering above the regular window underneatch.
1921 * If the mouse is now clicked, this would generate an ACTION_DOWN event, which would go to the
1922 * regular window. However, the trusted overlay is also watching for outside touch.
1923 * The trusted overlay should get two events:
1924 * 1) The ACTION_OUTSIDE event, since the click is now not inside its touchable region
1925 * 2) The HOVER_EXIT event, since the mouse pointer is no longer hovering inside this window
1926 *
1927 * This test reproduces a crash where there is an overlap between dispatch modes for the trusted
1928 * overlay touch target, since the event is causing both an ACTION_OUTSIDE, and as a HOVER_EXIT.
1929 */
1930TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlay) {
1931 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1932 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1933 ui::LogicalDisplayId::DEFAULT);
1934 overlay->setTrustedOverlay(true);
1935 overlay->setWatchOutsideTouch(true);
1936 overlay->setFrame(Rect(0, 0, 200, 200));
1937
1938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1939 ui::LogicalDisplayId::DEFAULT);
1940 window->setFrame(Rect(0, 0, 200, 200));
1941
1942 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1943 // Hover the mouse into the overlay
1944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1945 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1946 .build());
1947 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1948
1949 // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1950 // the regular window as the touch target
1951 overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1952 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1953
1954 // Now we can click with the mouse. The click should go into the regular window
1955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1956 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1957 .build());
1958 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1959 overlay->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
1960 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1961}
1962
1963/**
1964 * Similar to above, but also has a spy on top that also catches the HOVER
1965 * events. Also, instead of ACTION_DOWN, we are continuing to send the hovering
1966 * stream to ensure that the spy receives hover events correctly.
1967 */
1968TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlayWithSpy) {
1969 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1970 sp<FakeWindowHandle> spyWindow =
1971 sp<FakeWindowHandle>::make(app, mDispatcher, "Spy", ui::LogicalDisplayId::DEFAULT);
1972 spyWindow->setFrame(Rect(0, 0, 200, 200));
1973 spyWindow->setTrustedOverlay(true);
1974 spyWindow->setSpy(true);
1975 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1976 ui::LogicalDisplayId::DEFAULT);
1977 overlay->setTrustedOverlay(true);
1978 overlay->setWatchOutsideTouch(true);
1979 overlay->setFrame(Rect(0, 0, 200, 200));
1980
1981 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1982 ui::LogicalDisplayId::DEFAULT);
1983 window->setFrame(Rect(0, 0, 200, 200));
1984
1985 mDispatcher->onWindowInfosChanged(
1986 {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1987 // Hover the mouse into the overlay
1988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1989 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1990 .build());
1991 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1992 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1993
1994 // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1995 // the regular window as the touch target
1996 overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1997 mDispatcher->onWindowInfosChanged(
1998 {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1999
2000 // Now we can click with the mouse. The click should go into the regular window
2001 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2003 .build());
2004 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2005 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2006 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2007}
2008
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002009using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2010
2011/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002012 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2013 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002014 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002015TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002016 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002018 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2019 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002020 window->setFrame(Rect(0, 0, 200, 200));
2021
2022 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2023
2024 constexpr int32_t touchDeviceId = 4;
2025 constexpr int32_t stylusDeviceId = 2;
2026
2027 // Stylus down
2028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2029 .deviceId(stylusDeviceId)
2030 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2031 .build());
2032 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2033
2034 // Touch down
2035 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2036 .deviceId(touchDeviceId)
2037 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2038 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002039
2040 // Touch move
2041 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2042 .deviceId(touchDeviceId)
2043 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2044 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002045 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002046
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002047 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2049 .deviceId(stylusDeviceId)
2050 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2051 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002052 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2053 WithCoords(101, 111)));
2054
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002055 window->assertNoEvents();
2056}
2057
2058/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002059 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2060 * touch is not dropped, because multiple devices are allowed to be active in the same window.
2061 */
2062TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
2063 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2064 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002065 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2066 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002067 window->setFrame(Rect(0, 0, 200, 200));
2068
2069 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2070
2071 constexpr int32_t touchDeviceId = 4;
2072 constexpr int32_t stylusDeviceId = 2;
2073
2074 // Stylus down
2075 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2076 .deviceId(stylusDeviceId)
2077 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2078 .build());
2079 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2080
2081 // Touch down
2082 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2083 .deviceId(touchDeviceId)
2084 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2085 .build());
2086 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2087
2088 // Touch move
2089 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2090 .deviceId(touchDeviceId)
2091 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2092 .build());
2093 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2094
2095 // Stylus move
2096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2097 .deviceId(stylusDeviceId)
2098 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2099 .build());
2100 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2101 WithCoords(101, 111)));
2102
2103 window->assertNoEvents();
2104}
2105
2106/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002107 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002108 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002109 * Similar test as above, but with added SPY window.
2110 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002111TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002112 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002114 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2115 ui::LogicalDisplayId::DEFAULT);
2116 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2117 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002118 spyWindow->setFrame(Rect(0, 0, 200, 200));
2119 spyWindow->setTrustedOverlay(true);
2120 spyWindow->setSpy(true);
2121 window->setFrame(Rect(0, 0, 200, 200));
2122
2123 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2124
2125 constexpr int32_t touchDeviceId = 4;
2126 constexpr int32_t stylusDeviceId = 2;
2127
2128 // Stylus down
2129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2130 .deviceId(stylusDeviceId)
2131 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2132 .build());
2133 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2134 spyWindow->consumeMotionEvent(
2135 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2136
2137 // Touch down
2138 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2139 .deviceId(touchDeviceId)
2140 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2141 .build());
2142
2143 // Touch move
2144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2145 .deviceId(touchDeviceId)
2146 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2147 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002148
2149 // Touch is ignored because stylus is already down
2150
2151 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2153 .deviceId(stylusDeviceId)
2154 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2155 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002156 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2157 WithCoords(101, 111)));
2158 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2159 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002160
2161 window->assertNoEvents();
2162 spyWindow->assertNoEvents();
2163}
2164
2165/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002166 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2167 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2168 * Similar test as above, but with added SPY window.
2169 */
2170TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2171 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002173 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2174 ui::LogicalDisplayId::DEFAULT);
2175 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2176 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002177 spyWindow->setFrame(Rect(0, 0, 200, 200));
2178 spyWindow->setTrustedOverlay(true);
2179 spyWindow->setSpy(true);
2180 window->setFrame(Rect(0, 0, 200, 200));
2181
2182 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2183
2184 constexpr int32_t touchDeviceId = 4;
2185 constexpr int32_t stylusDeviceId = 2;
2186
2187 // Stylus down
2188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2189 .deviceId(stylusDeviceId)
2190 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2191 .build());
2192 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2193 spyWindow->consumeMotionEvent(
2194 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2195
2196 // Touch down
2197 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2198 .deviceId(touchDeviceId)
2199 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2200 .build());
2201 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2202 spyWindow->consumeMotionEvent(
2203 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2204
2205 // Touch move
2206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2207 .deviceId(touchDeviceId)
2208 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2209 .build());
2210 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2211 spyWindow->consumeMotionEvent(
2212 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2213
2214 // Subsequent stylus movements are delivered correctly
2215 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2216 .deviceId(stylusDeviceId)
2217 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2218 .build());
2219 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2220 WithCoords(101, 111)));
2221 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2222 WithCoords(101, 111)));
2223
2224 window->assertNoEvents();
2225 spyWindow->assertNoEvents();
2226}
2227
2228/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002229 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002230 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002231 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002232TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002233 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002235 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2236 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002237 window->setFrame(Rect(0, 0, 200, 200));
2238
2239 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2240
2241 constexpr int32_t touchDeviceId = 4;
2242 constexpr int32_t stylusDeviceId = 2;
2243
2244 // Stylus down on the window
2245 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2246 .deviceId(stylusDeviceId)
2247 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2248 .build());
2249 window->consumeMotionEvent(
2250 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2251
2252 // Touch down on window
2253 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2254 .deviceId(touchDeviceId)
2255 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2256 .build());
2257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2258 .deviceId(touchDeviceId)
2259 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2260 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002261
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002262 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002263
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002264 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2266 .deviceId(stylusDeviceId)
2267 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2268 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002269 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2270 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002271
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002272 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002273 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2274 .deviceId(touchDeviceId)
2275 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2276 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002277 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002278}
2279
2280/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002281 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2282 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2283 */
2284TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2285 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2286 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002287 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2288 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002289 window->setFrame(Rect(0, 0, 200, 200));
2290
2291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2292
2293 constexpr int32_t touchDeviceId = 4;
2294 constexpr int32_t stylusDeviceId = 2;
2295
2296 // Stylus down on the window
2297 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2298 .deviceId(stylusDeviceId)
2299 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2300 .build());
2301 window->consumeMotionEvent(
2302 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2303
2304 // Touch down on window
2305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2306 .deviceId(touchDeviceId)
2307 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2308 .build());
2309 // Touch move on window
2310 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2311 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2312 .deviceId(touchDeviceId)
2313 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2314 .build());
2315 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2316
2317 // Subsequent stylus movements are delivered correctly
2318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2319 .deviceId(stylusDeviceId)
2320 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2321 .build());
2322 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2323 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2324
2325 // and subsequent touches continue to work
2326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2327 .deviceId(touchDeviceId)
2328 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2329 .build());
2330 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2331 window->assertNoEvents();
2332}
2333
2334/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002335 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002336 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002337 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002338TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002339 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002341 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2342 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002343 window->setFrame(Rect(0, 0, 200, 200));
2344
2345 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2346
2347 constexpr int32_t touchDeviceId = 4;
2348 constexpr int32_t stylusDeviceId = 2;
2349
2350 // Touch down on window
2351 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2352 .deviceId(touchDeviceId)
2353 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2354 .build());
2355 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2356 .deviceId(touchDeviceId)
2357 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2358 .build());
2359 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2360 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2361
2362 // Stylus hover on the window
2363 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2364 .deviceId(stylusDeviceId)
2365 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2366 .build());
2367 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2368 .deviceId(stylusDeviceId)
2369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2370 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002371 // Stylus hover movement causes touch to be canceled
2372 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2373 WithCoords(141, 146)));
2374 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2375 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2376 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2377 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002378
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002379 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002380 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2381 .deviceId(touchDeviceId)
2382 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2383 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002384
2385 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002386}
2387
2388/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002389 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2390 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2391 */
2392TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2393 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2394 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002395 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2396 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002397 window->setFrame(Rect(0, 0, 200, 200));
2398
2399 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2400
2401 constexpr int32_t touchDeviceId = 4;
2402 constexpr int32_t stylusDeviceId = 2;
2403
2404 // Touch down on window
2405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2406 .deviceId(touchDeviceId)
2407 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2408 .build());
2409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2410 .deviceId(touchDeviceId)
2411 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2412 .build());
2413 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2414 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2415
2416 // Stylus hover on the window
2417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2418 .deviceId(stylusDeviceId)
2419 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2420 .build());
2421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2422 .deviceId(stylusDeviceId)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2424 .build());
2425 // Stylus hover movement is received normally
2426 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2427 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2428 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2429 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2430
2431 // Subsequent touch movements also work
2432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2433 .deviceId(touchDeviceId)
2434 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2435 .build());
2436 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2437 WithCoords(142, 147)));
2438
2439 window->assertNoEvents();
2440}
2441
2442/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002443 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2444 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2445 * become active.
2446 */
2447TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002448 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002450 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2451 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002452 window->setFrame(Rect(0, 0, 200, 200));
2453
2454 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2455
2456 constexpr int32_t stylusDeviceId1 = 3;
2457 constexpr int32_t stylusDeviceId2 = 5;
2458
2459 // Touch down on window
2460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2461 .deviceId(stylusDeviceId1)
2462 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2463 .build());
2464 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2465 .deviceId(stylusDeviceId1)
2466 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2467 .build());
2468 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2469 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2470
2471 // Second stylus down
2472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2473 .deviceId(stylusDeviceId2)
2474 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2475 .build());
2476 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2477 .deviceId(stylusDeviceId2)
2478 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2479 .build());
2480
2481 // First stylus is canceled, second one takes over.
2482 window->consumeMotionEvent(
2483 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2484 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2486
2487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2488 .deviceId(stylusDeviceId1)
2489 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2490 .build());
2491 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002492 window->assertNoEvents();
2493}
2494
2495/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002496 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2497 * both stylus devices can function simultaneously.
2498 */
2499TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2500 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2501 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002502 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2503 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002504 window->setFrame(Rect(0, 0, 200, 200));
2505
2506 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2507
2508 constexpr int32_t stylusDeviceId1 = 3;
2509 constexpr int32_t stylusDeviceId2 = 5;
2510
2511 // Touch down on window
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2513 .deviceId(stylusDeviceId1)
2514 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2515 .build());
2516 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2517 .deviceId(stylusDeviceId1)
2518 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2519 .build());
2520 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2521 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2522
2523 // Second stylus down
2524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2525 .deviceId(stylusDeviceId2)
2526 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2527 .build());
2528 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2529 .deviceId(stylusDeviceId2)
2530 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2531 .build());
2532 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2533 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2534
2535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2536 .deviceId(stylusDeviceId1)
2537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2538 .build());
2539 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2540 window->assertNoEvents();
2541}
2542
2543/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002544 * One window. Touch down on the window. Then, stylus down on the window from another device.
2545 * Ensure that is canceled, because stylus down should be preferred over touch.
2546 */
2547TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002548 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2551 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002552 window->setFrame(Rect(0, 0, 200, 200));
2553
2554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2555
2556 constexpr int32_t touchDeviceId = 4;
2557 constexpr int32_t stylusDeviceId = 2;
2558
2559 // Touch down on window
2560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2561 .deviceId(touchDeviceId)
2562 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2563 .build());
2564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2565 .deviceId(touchDeviceId)
2566 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2567 .build());
2568 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2569 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2570
2571 // Stylus down on the window
2572 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2573 .deviceId(stylusDeviceId)
2574 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2575 .build());
2576 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2577 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2578
2579 // Subsequent stylus movements are delivered correctly
2580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2581 .deviceId(stylusDeviceId)
2582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2583 .build());
2584 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2585 WithCoords(101, 111)));
2586}
2587
2588/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002589 * One window. Touch down on the window. Then, stylus down on the window from another device.
2590 * Ensure that both touch and stylus are functioning independently.
2591 */
2592TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2593 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2594 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002595 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2596 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002597 window->setFrame(Rect(0, 0, 200, 200));
2598
2599 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2600
2601 constexpr int32_t touchDeviceId = 4;
2602 constexpr int32_t stylusDeviceId = 2;
2603
2604 // Touch down on window
2605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2606 .deviceId(touchDeviceId)
2607 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2608 .build());
2609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2612 .build());
2613 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2614 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2615
2616 // Stylus down on the window
2617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2618 .deviceId(stylusDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2620 .build());
2621 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2622
2623 // Subsequent stylus movements are delivered correctly
2624 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2625 .deviceId(stylusDeviceId)
2626 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2627 .build());
2628 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2629 WithCoords(101, 111)));
2630
2631 // Touch continues to work too
2632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2633 .deviceId(touchDeviceId)
2634 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2635 .build());
2636 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2637}
2638
2639/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002640 * Two windows: a window on the left and a window on the right.
2641 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2642 * down. Then, on the left window, also place second touch pointer down.
2643 * This test tries to reproduce a crash.
2644 * In the buggy implementation, second pointer down on the left window would cause a crash.
2645 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002646TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2647 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002649 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2650 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002651 leftWindow->setFrame(Rect(0, 0, 200, 200));
2652
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002653 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2654 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002655 rightWindow->setFrame(Rect(200, 0, 400, 200));
2656
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002657 mDispatcher->onWindowInfosChanged(
2658 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002659
2660 const int32_t touchDeviceId = 4;
2661 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002662
2663 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2665 .deviceId(mouseDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2667 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002668 leftWindow->consumeMotionEvent(
2669 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2670
2671 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2673 .deviceId(mouseDeviceId)
2674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2676 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002677
2678 leftWindow->consumeMotionEvent(
2679 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2680 leftWindow->consumeMotionEvent(
2681 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2682
Prabir Pradhan678438e2023-04-13 19:32:51 +00002683 mDispatcher->notifyMotion(
2684 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2685 .deviceId(mouseDeviceId)
2686 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2687 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2688 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2689 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002690 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2691
2692 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
2695 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2696 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002697 leftWindow->assertNoEvents();
2698
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002699 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2700
2701 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002702 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2703 .deviceId(touchDeviceId)
2704 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2705 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2706 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002707 // Since this is now a new splittable pointer going down on the left window, and it's coming
2708 // from a different device, the current gesture in the left window (pointer down) should first
2709 // be canceled.
2710 leftWindow->consumeMotionEvent(
2711 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002712 leftWindow->consumeMotionEvent(
2713 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2714 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2715 // current implementation.
2716 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2717 rightWindow->consumeMotionEvent(
2718 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2719
2720 leftWindow->assertNoEvents();
2721 rightWindow->assertNoEvents();
2722}
2723
2724/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002725 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002726 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2727 * down. Then, on the left window, also place second touch pointer down.
2728 * This test tries to reproduce a crash.
2729 * In the buggy implementation, second pointer down on the left window would cause a crash.
2730 */
2731TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2732 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002734 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2735 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002736 leftWindow->setFrame(Rect(0, 0, 200, 200));
2737
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002738 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2739 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002740 rightWindow->setFrame(Rect(200, 0, 400, 200));
2741
2742 mDispatcher->onWindowInfosChanged(
2743 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2744
2745 const int32_t touchDeviceId = 4;
2746 const int32_t mouseDeviceId = 6;
2747
2748 // Start hovering over the left window
2749 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2750 .deviceId(mouseDeviceId)
2751 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2752 .build());
2753 leftWindow->consumeMotionEvent(
2754 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2755
2756 // Mouse down on left window
2757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2758 .deviceId(mouseDeviceId)
2759 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2761 .build());
2762
2763 leftWindow->consumeMotionEvent(
2764 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2765 leftWindow->consumeMotionEvent(
2766 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2767
2768 mDispatcher->notifyMotion(
2769 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2770 .deviceId(mouseDeviceId)
2771 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2772 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2773 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2774 .build());
2775 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2776
2777 // First touch pointer down on right window
2778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2779 .deviceId(touchDeviceId)
2780 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2781 .build());
2782 leftWindow->assertNoEvents();
2783
2784 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2785
2786 // Second touch pointer down on left window
2787 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2788 .deviceId(touchDeviceId)
2789 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2790 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2791 .build());
2792 // Since this is now a new splittable pointer going down on the left window, and it's coming
2793 // from a different device, it will be split and delivered to left window separately.
2794 leftWindow->consumeMotionEvent(
2795 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2796 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2797 // current implementation.
2798 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2799 rightWindow->consumeMotionEvent(
2800 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2801
2802 leftWindow->assertNoEvents();
2803 rightWindow->assertNoEvents();
2804}
2805
2806/**
2807 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002808 * Mouse is hovered on the left window and stylus is hovered on the right window.
2809 */
2810TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002812 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2813 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002814 leftWindow->setFrame(Rect(0, 0, 200, 200));
2815
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002816 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2817 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002818 rightWindow->setFrame(Rect(200, 0, 400, 200));
2819
2820 mDispatcher->onWindowInfosChanged(
2821 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2822
2823 const int32_t stylusDeviceId = 3;
2824 const int32_t mouseDeviceId = 6;
2825
2826 // Start hovering over the left window
2827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2828 .deviceId(mouseDeviceId)
2829 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2830 .build());
2831 leftWindow->consumeMotionEvent(
2832 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2833
2834 // Stylus hovered on right window
2835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2836 .deviceId(stylusDeviceId)
2837 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2838 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002839 rightWindow->consumeMotionEvent(
2840 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2841
2842 // Subsequent HOVER_MOVE events are dispatched correctly.
2843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2844 .deviceId(mouseDeviceId)
2845 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2846 .build());
2847 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002848 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002849
2850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2851 .deviceId(stylusDeviceId)
2852 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2853 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002854 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002855 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002856
2857 leftWindow->assertNoEvents();
2858 rightWindow->assertNoEvents();
2859}
2860
2861/**
2862 * Three windows: a window on the left and a window on the right.
2863 * And a spy window that's positioned above all of them.
2864 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2865 * Check the stream that's received by the spy.
2866 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002867TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2868 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002869 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2870
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002871 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2872 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002873 spyWindow->setFrame(Rect(0, 0, 400, 400));
2874 spyWindow->setTrustedOverlay(true);
2875 spyWindow->setSpy(true);
2876
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002877 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2878 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002879 leftWindow->setFrame(Rect(0, 0, 200, 200));
2880
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002881 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2882 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002883
2884 rightWindow->setFrame(Rect(200, 0, 400, 200));
2885
2886 mDispatcher->onWindowInfosChanged(
2887 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2888
2889 const int32_t stylusDeviceId = 1;
2890 const int32_t touchDeviceId = 2;
2891
2892 // Stylus down on the left window
2893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2894 .deviceId(stylusDeviceId)
2895 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2896 .build());
2897 leftWindow->consumeMotionEvent(
2898 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2899 spyWindow->consumeMotionEvent(
2900 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2901
2902 // Touch down on the right window
2903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2904 .deviceId(touchDeviceId)
2905 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2906 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002907 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002908 rightWindow->consumeMotionEvent(
2909 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002910
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002911 // Spy window does not receive touch events, because stylus events take precedence, and it
2912 // already has an active stylus gesture.
2913
2914 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2916 .deviceId(stylusDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2918 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002919 leftWindow->consumeMotionEvent(
2920 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2921 spyWindow->consumeMotionEvent(
2922 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002923
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002924 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2926 .deviceId(touchDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2928 .build());
2929 rightWindow->consumeMotionEvent(
2930 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002931
2932 spyWindow->assertNoEvents();
2933 leftWindow->assertNoEvents();
2934 rightWindow->assertNoEvents();
2935}
2936
2937/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002938 * Three windows: a window on the left and a window on the right.
2939 * And a spy window that's positioned above all of them.
2940 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2941 * Check the stream that's received by the spy.
2942 */
2943TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2944 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2945 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2946
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002947 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2948 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002949 spyWindow->setFrame(Rect(0, 0, 400, 400));
2950 spyWindow->setTrustedOverlay(true);
2951 spyWindow->setSpy(true);
2952
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002953 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2954 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002955 leftWindow->setFrame(Rect(0, 0, 200, 200));
2956
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002957 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2958 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002959
2960 rightWindow->setFrame(Rect(200, 0, 400, 200));
2961
2962 mDispatcher->onWindowInfosChanged(
2963 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2964
2965 const int32_t stylusDeviceId = 1;
2966 const int32_t touchDeviceId = 2;
2967
2968 // Stylus down on the left window
2969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2970 .deviceId(stylusDeviceId)
2971 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2972 .build());
2973 leftWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2975 spyWindow->consumeMotionEvent(
2976 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2977
2978 // Touch down on the right window
2979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2980 .deviceId(touchDeviceId)
2981 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2982 .build());
2983 leftWindow->assertNoEvents();
2984 rightWindow->consumeMotionEvent(
2985 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2986 spyWindow->consumeMotionEvent(
2987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2988
2989 // Stylus movements continue. They should be delivered to the left window and to the spy window
2990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2991 .deviceId(stylusDeviceId)
2992 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2993 .build());
2994 leftWindow->consumeMotionEvent(
2995 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2996 spyWindow->consumeMotionEvent(
2997 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2998
2999 // Further touch MOVE events keep going to the right window and to the spy
3000 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3001 .deviceId(touchDeviceId)
3002 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3003 .build());
3004 rightWindow->consumeMotionEvent(
3005 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3006 spyWindow->consumeMotionEvent(
3007 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3008
3009 spyWindow->assertNoEvents();
3010 leftWindow->assertNoEvents();
3011 rightWindow->assertNoEvents();
3012}
3013
3014/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003015 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3016 * both.
3017 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003018 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003019 * At the same time, left and right should be getting independent streams of hovering and touch,
3020 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003021 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003022TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003023 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003024 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3025
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003026 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3027 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003028 spyWindow->setFrame(Rect(0, 0, 400, 400));
3029 spyWindow->setTrustedOverlay(true);
3030 spyWindow->setSpy(true);
3031
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003032 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3033 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003034 leftWindow->setFrame(Rect(0, 0, 200, 200));
3035
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003036 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3037 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003038 rightWindow->setFrame(Rect(200, 0, 400, 200));
3039
3040 mDispatcher->onWindowInfosChanged(
3041 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3042
3043 const int32_t stylusDeviceId = 1;
3044 const int32_t touchDeviceId = 2;
3045
3046 // Stylus hover on the left window
3047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3048 .deviceId(stylusDeviceId)
3049 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3050 .build());
3051 leftWindow->consumeMotionEvent(
3052 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3053 spyWindow->consumeMotionEvent(
3054 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3055
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003056 // Touch down on the right window. Spy doesn't receive this touch because it already has
3057 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3059 .deviceId(touchDeviceId)
3060 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3061 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003062 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003063 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003064 rightWindow->consumeMotionEvent(
3065 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3066
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003067 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3069 .deviceId(stylusDeviceId)
3070 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3071 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003072 leftWindow->consumeMotionEvent(
3073 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003074 spyWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003076
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3079 .deviceId(touchDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3081 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003082 rightWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3084
3085 spyWindow->assertNoEvents();
3086 leftWindow->assertNoEvents();
3087 rightWindow->assertNoEvents();
3088}
3089
3090/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003091 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3092 * both.
3093 * Check hover in left window and touch down in the right window.
3094 * At first, spy should receive hover. Next, spy should receive touch.
3095 * At the same time, left and right should be getting independent streams of hovering and touch,
3096 * respectively.
3097 */
3098TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3099 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3101
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003102 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3103 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003104 spyWindow->setFrame(Rect(0, 0, 400, 400));
3105 spyWindow->setTrustedOverlay(true);
3106 spyWindow->setSpy(true);
3107
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003108 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3109 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003110 leftWindow->setFrame(Rect(0, 0, 200, 200));
3111
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003112 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3113 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003114 rightWindow->setFrame(Rect(200, 0, 400, 200));
3115
3116 mDispatcher->onWindowInfosChanged(
3117 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3118
3119 const int32_t stylusDeviceId = 1;
3120 const int32_t touchDeviceId = 2;
3121
3122 // Stylus hover on the left window
3123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3124 .deviceId(stylusDeviceId)
3125 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3126 .build());
3127 leftWindow->consumeMotionEvent(
3128 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3129 spyWindow->consumeMotionEvent(
3130 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3131
3132 // Touch down on the right window.
3133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3134 .deviceId(touchDeviceId)
3135 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3136 .build());
3137 leftWindow->assertNoEvents();
3138 spyWindow->consumeMotionEvent(
3139 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3140 rightWindow->consumeMotionEvent(
3141 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3142
3143 // Stylus movements continue. They should be delivered to the left window and the spy.
3144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3145 .deviceId(stylusDeviceId)
3146 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3147 .build());
3148 leftWindow->consumeMotionEvent(
3149 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3150 spyWindow->consumeMotionEvent(
3151 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3152
3153 // Touch movements continue. They should be delivered to the right window and the spy
3154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3155 .deviceId(touchDeviceId)
3156 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3157 .build());
3158 rightWindow->consumeMotionEvent(
3159 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3160 spyWindow->consumeMotionEvent(
3161 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3162
3163 spyWindow->assertNoEvents();
3164 leftWindow->assertNoEvents();
3165 rightWindow->assertNoEvents();
3166}
3167
3168/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003169 * On a single window, use two different devices: mouse and touch.
3170 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3171 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3172 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3173 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3174 * represent a new gesture.
3175 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003176TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3177 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003178 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003179 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3180 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003181 window->setFrame(Rect(0, 0, 400, 400));
3182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003183 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003184
3185 const int32_t touchDeviceId = 4;
3186 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003187
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003188 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003193 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003194 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3195 .deviceId(touchDeviceId)
3196 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3197 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3198 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003199 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003200 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3201 .deviceId(touchDeviceId)
3202 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3203 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3204 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003205 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3206 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3207 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3208
3209 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3211 .deviceId(mouseDeviceId)
3212 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3213 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3214 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003215
3216 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003217 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003218 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3219
Prabir Pradhan678438e2023-04-13 19:32:51 +00003220 mDispatcher->notifyMotion(
3221 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3222 .deviceId(mouseDeviceId)
3223 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3224 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3225 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3226 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003227 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3228
3229 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003230 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3231 .deviceId(touchDeviceId)
3232 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3233 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3234 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003235 // Since we already canceled this touch gesture, it will be ignored until a completely new
3236 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3237 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3238 // However, mouse movements should continue to work.
3239 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3240 .deviceId(mouseDeviceId)
3241 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3242 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3243 .build());
3244 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3245
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003246 window->assertNoEvents();
3247}
3248
3249/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003250 * On a single window, use two different devices: mouse and touch.
3251 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3252 * Mouse is clicked next, which should not interfere with the touch stream.
3253 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3254 * delivered correctly.
3255 */
3256TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3257 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003259 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3260 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003261 window->setFrame(Rect(0, 0, 400, 400));
3262
3263 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3264
3265 const int32_t touchDeviceId = 4;
3266 const int32_t mouseDeviceId = 6;
3267
3268 // First touch pointer down
3269 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
3271 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3272 .build());
3273 // Second touch pointer down
3274 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3275 .deviceId(touchDeviceId)
3276 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3277 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3278 .build());
3279 // First touch pointer lifts. The second one remains down
3280 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3281 .deviceId(touchDeviceId)
3282 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3283 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3284 .build());
3285 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3286 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3287 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3288
3289 // Mouse down
3290 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3291 .deviceId(mouseDeviceId)
3292 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3294 .build());
3295
3296 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3297
3298 mDispatcher->notifyMotion(
3299 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3300 .deviceId(mouseDeviceId)
3301 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3302 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3303 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3304 .build());
3305 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3306
3307 // Second touch pointer down.
3308 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3309 .deviceId(touchDeviceId)
3310 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3311 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3312 .build());
3313 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3314 WithPointerCount(2u)));
3315
3316 // Mouse movements should continue to work
3317 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3318 .deviceId(mouseDeviceId)
3319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3321 .build());
3322 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3323
3324 window->assertNoEvents();
3325}
3326
3327/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003328 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3329 * the injected event.
3330 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003331TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3332 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003334 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3335 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003336 window->setFrame(Rect(0, 0, 400, 400));
3337
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003338 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003339
3340 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003341 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3342 // completion.
3343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003344 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003345 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3346 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003348 .build()));
3349 window->consumeMotionEvent(
3350 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3351
3352 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3353 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3355 .deviceId(touchDeviceId)
3356 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3357 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003358
3359 window->consumeMotionEvent(
3360 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3361 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3362}
3363
3364/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003365 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3366 * parallel to the injected event.
3367 */
3368TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3369 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003371 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3372 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003373 window->setFrame(Rect(0, 0, 400, 400));
3374
3375 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3376
3377 const int32_t touchDeviceId = 4;
3378 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3379 // completion.
3380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3381 injectMotionEvent(*mDispatcher,
3382 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3383 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3384 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3385 .build()));
3386 window->consumeMotionEvent(
3387 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3388
3389 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3390 // allowed through.
3391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3392 .deviceId(touchDeviceId)
3393 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3394 .build());
3395 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3396}
3397
3398/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003399 * This test is similar to the test above, but the sequence of injected events is different.
3400 *
3401 * Two windows: a window on the left and a window on the right.
3402 * Mouse is hovered over the left window.
3403 * Next, we tap on the left window, where the cursor was last seen.
3404 *
3405 * After that, we inject one finger down onto the right window, and then a second finger down onto
3406 * the left window.
3407 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3408 * window (first), and then another on the left window (second).
3409 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3410 * In the buggy implementation, second finger down on the left window would cause a crash.
3411 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003412TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3413 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003415 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3416 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003417 leftWindow->setFrame(Rect(0, 0, 200, 200));
3418
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003419 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3420 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003421 rightWindow->setFrame(Rect(200, 0, 400, 200));
3422
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003423 mDispatcher->onWindowInfosChanged(
3424 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003425
3426 const int32_t mouseDeviceId = 6;
3427 const int32_t touchDeviceId = 4;
3428 // Hover over the left window. Keep the cursor there.
3429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003430 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003431 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3432 AINPUT_SOURCE_MOUSE)
3433 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003434 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003435 .build()));
3436 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3437
3438 // Tap on left window
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_DOWN,
3442 AINPUT_SOURCE_TOUCHSCREEN)
3443 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003444 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003445 .build()));
3446
3447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003448 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003449 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3450 AINPUT_SOURCE_TOUCHSCREEN)
3451 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003452 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003453 .build()));
3454 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3455 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3456 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3457
3458 // First finger down on right window
3459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003460 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003461 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3462 AINPUT_SOURCE_TOUCHSCREEN)
3463 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003464 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003465 .build()));
3466 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3467
3468 // Second finger down on the left 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(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3472 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003473 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3474 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003475 .build()));
3476 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3477 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3478
3479 // No more events
3480 leftWindow->assertNoEvents();
3481 rightWindow->assertNoEvents();
3482}
3483
3484/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003485 * This test is similar to the test above, but the sequence of injected events is different.
3486 *
3487 * Two windows: a window on the left and a window on the right.
3488 * Mouse is hovered over the left window.
3489 * Next, we tap on the left window, where the cursor was last seen.
3490 *
3491 * After that, we send one finger down onto the right window, and then a second finger down onto
3492 * the left window.
3493 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3494 * window (first), and then another on the left window (second).
3495 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3496 * In the buggy implementation, second finger down on the left window would cause a crash.
3497 */
3498TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3499 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003501 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3502 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003503 leftWindow->setFrame(Rect(0, 0, 200, 200));
3504
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003505 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3506 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003507 rightWindow->setFrame(Rect(200, 0, 400, 200));
3508
3509 mDispatcher->onWindowInfosChanged(
3510 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3511
3512 const int32_t mouseDeviceId = 6;
3513 const int32_t touchDeviceId = 4;
3514 // Hover over the left window. Keep the cursor there.
3515 mDispatcher->notifyMotion(
3516 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3517 .deviceId(mouseDeviceId)
3518 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3519 .build());
3520 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3521
3522 // Tap on left window
3523 mDispatcher->notifyMotion(
3524 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3525 .deviceId(touchDeviceId)
3526 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3527 .build());
3528
3529 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3530 .deviceId(touchDeviceId)
3531 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3532 .build());
3533 leftWindow->consumeMotionEvent(
3534 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3535 leftWindow->consumeMotionEvent(
3536 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3537
3538 // First finger down on right window
3539 mDispatcher->notifyMotion(
3540 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3541 .deviceId(touchDeviceId)
3542 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3543 .build());
3544 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3545
3546 // Second finger down on the left window
3547 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3548 .deviceId(touchDeviceId)
3549 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3550 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3551 .build());
3552 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3553 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3554
3555 // No more events
3556 leftWindow->assertNoEvents();
3557 rightWindow->assertNoEvents();
3558}
3559
3560/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003561 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3562 * While the touch is down, new hover events from the stylus device should be ignored. After the
3563 * touch is gone, stylus hovering should start working again.
3564 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003565TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003566 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003568 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3569 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003570 window->setFrame(Rect(0, 0, 200, 200));
3571
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003572 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003573
3574 const int32_t stylusDeviceId = 5;
3575 const int32_t touchDeviceId = 4;
3576 // Start hovering with stylus
3577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003578 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003579 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003580 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003581 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003582 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003583 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003584
3585 // Finger down on the window
3586 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003587 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003588 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003589 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003590 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003591 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003592 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003593
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003594 // Continue hovering with stylus.
3595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003596 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003597 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3598 AINPUT_SOURCE_STYLUS)
3599 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003600 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003601 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003602 // Hovers continue to work
3603 window->consumeMotionEvent(
3604 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003605
3606 // Lift up the finger
3607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003608 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003609 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3610 AINPUT_SOURCE_TOUCHSCREEN)
3611 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003612 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003613 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003614
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003616 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003617 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3618 AINPUT_SOURCE_STYLUS)
3619 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003620 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003621 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003622 window->consumeMotionEvent(
3623 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003624 window->assertNoEvents();
3625}
3626
3627/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003628 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3629 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3630 * check that the stylus hovering continues to work.
3631 */
3632TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3633 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3634 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003635 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3636 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003637 window->setFrame(Rect(0, 0, 200, 200));
3638
3639 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3640
3641 const int32_t stylusDeviceId = 5;
3642 const int32_t touchDeviceId = 4;
3643 // Start hovering with stylus
3644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3645 .deviceId(stylusDeviceId)
3646 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3647 .build());
3648 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3649
3650 // Finger down on the window
3651 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3652 .deviceId(touchDeviceId)
3653 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3654 .build());
3655 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3656
3657 // Continue hovering with stylus.
3658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3659 .deviceId(stylusDeviceId)
3660 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3661 .build());
3662 // Hovers continue to work
3663 window->consumeMotionEvent(
3664 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3665
3666 // Lift up the finger
3667 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3668 .deviceId(touchDeviceId)
3669 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3670 .build());
3671 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3672
3673 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3674 .deviceId(stylusDeviceId)
3675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3676 .build());
3677 window->consumeMotionEvent(
3678 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3679 window->assertNoEvents();
3680}
3681
3682/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003683 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3684 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3685 *
3686 * Two windows: one on the left and one on the right.
3687 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3688 * Stylus down on the left window, and then touch down on the right window.
3689 * Check that the right window doesn't get touches while the stylus is down on the left window.
3690 */
3691TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3692 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3693 sp<FakeWindowHandle> leftWindow =
3694 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003695 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003696 leftWindow->setFrame(Rect(0, 0, 100, 100));
3697
3698 sp<FakeWindowHandle> sbtRightWindow =
3699 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003700 "Stylus blocks touch (right) window",
3701 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003702 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3703 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3704
3705 mDispatcher->onWindowInfosChanged(
3706 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3707
3708 const int32_t stylusDeviceId = 5;
3709 const int32_t touchDeviceId = 4;
3710
3711 // Stylus down in the left window
3712 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3713 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3714 .deviceId(stylusDeviceId)
3715 .build());
3716 leftWindow->consumeMotionEvent(
3717 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3718
3719 // Finger tap on the right window
3720 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3721 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3722 .deviceId(touchDeviceId)
3723 .build());
3724 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3725 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3726 .deviceId(touchDeviceId)
3727 .build());
3728
3729 // The touch should be blocked, because stylus is down somewhere else on screen!
3730 sbtRightWindow->assertNoEvents();
3731
3732 // Continue stylus motion, and ensure it's not impacted.
3733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3734 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3735 .deviceId(stylusDeviceId)
3736 .build());
3737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3738 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3739 .deviceId(stylusDeviceId)
3740 .build());
3741 leftWindow->consumeMotionEvent(
3742 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3743 leftWindow->consumeMotionEvent(
3744 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3745
3746 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3748 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3749 .deviceId(touchDeviceId)
3750 .build());
3751 sbtRightWindow->consumeMotionEvent(
3752 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3753}
3754
3755/**
3756 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3757 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3758 *
3759 * Two windows: one on the left and one on the right.
3760 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3761 * Stylus hover on the left window, and then touch down on the right window.
3762 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3763 */
3764TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3765 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3766 sp<FakeWindowHandle> leftWindow =
3767 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003768 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003769 leftWindow->setFrame(Rect(0, 0, 100, 100));
3770
3771 sp<FakeWindowHandle> sbtRightWindow =
3772 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003773 "Stylus blocks touch (right) window",
3774 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003775 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3776 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3777
3778 mDispatcher->onWindowInfosChanged(
3779 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3780
3781 const int32_t stylusDeviceId = 5;
3782 const int32_t touchDeviceId = 4;
3783
3784 // Stylus hover in the left window
3785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3787 .deviceId(stylusDeviceId)
3788 .build());
3789 leftWindow->consumeMotionEvent(
3790 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3791
3792 // Finger tap on the right window
3793 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3794 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3795 .deviceId(touchDeviceId)
3796 .build());
3797 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3798 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3799 .deviceId(touchDeviceId)
3800 .build());
3801
3802 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3803 sbtRightWindow->assertNoEvents();
3804
3805 // Continue stylus motion, and ensure it's not impacted.
3806 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3807 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3808 .deviceId(stylusDeviceId)
3809 .build());
3810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3811 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3812 .deviceId(stylusDeviceId)
3813 .build());
3814 leftWindow->consumeMotionEvent(
3815 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3816 leftWindow->consumeMotionEvent(
3817 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3818
3819 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3821 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3822 .deviceId(touchDeviceId)
3823 .build());
3824 sbtRightWindow->consumeMotionEvent(
3825 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3826}
3827
3828/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003829 * A spy window above a window with no input channel.
3830 * Start hovering with a stylus device, and then tap with it.
3831 * Ensure spy window receives the entire sequence.
3832 */
3833TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003835 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3836 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003837 spyWindow->setFrame(Rect(0, 0, 200, 200));
3838 spyWindow->setTrustedOverlay(true);
3839 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003840 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3841 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003842 window->setNoInputChannel(true);
3843 window->setFrame(Rect(0, 0, 200, 200));
3844
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003845 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003846
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003847 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003848 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3849 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3850 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003851 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3852 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3855 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003856 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3857
3858 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3860 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3861 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003862 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3863
3864 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3866 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3867 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003868 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3869
3870 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3872 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3873 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003874 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3875 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3877 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3878 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003879 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3880
3881 // No more events
3882 spyWindow->assertNoEvents();
3883 window->assertNoEvents();
3884}
3885
3886/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003887 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3888 * rejected. But since we already have an ongoing gesture, this event should be processed.
3889 * This prevents inconsistent events being handled inside the dispatcher.
3890 */
3891TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3893
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003894 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3895 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003896 window->setFrame(Rect(0, 0, 200, 200));
3897
3898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3899
3900 // Start hovering with stylus
3901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3902 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3903 .build());
3904 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3905
3906 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3907 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3908 .build();
3909 // Make this 'hoverExit' event stale
3910 mFakePolicy->setStaleEventTimeout(100ms);
3911 std::this_thread::sleep_for(100ms);
3912
3913 // It shouldn't be dropped by the dispatcher, even though it's stale.
3914 mDispatcher->notifyMotion(hoverExit);
3915 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3916
3917 // Stylus starts hovering again! There should be no crash.
3918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3919 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3920 .build());
3921 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3922}
3923
3924/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003925 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3926 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3927 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3928 * While the mouse is down, new move events from the touch device should be ignored.
3929 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003930TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3931 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003932 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003933 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3934 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 spyWindow->setFrame(Rect(0, 0, 200, 200));
3936 spyWindow->setTrustedOverlay(true);
3937 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3939 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003940 window->setFrame(Rect(0, 0, 200, 200));
3941
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003942 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003943
3944 const int32_t mouseDeviceId = 7;
3945 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003946
3947 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003948 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3949 .deviceId(mouseDeviceId)
3950 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3951 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003952 spyWindow->consumeMotionEvent(
3953 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3954 window->consumeMotionEvent(
3955 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3956
3957 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3959 .deviceId(touchDeviceId)
3960 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3961 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003962 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3963 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3964 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3965 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3966
Prabir Pradhan678438e2023-04-13 19:32:51 +00003967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3968 .deviceId(touchDeviceId)
3969 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3970 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003971 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3972 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3973
3974 // Pilfer the stream
3975 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3976 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3977
Prabir Pradhan678438e2023-04-13 19:32:51 +00003978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3979 .deviceId(touchDeviceId)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3981 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003982 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3983
3984 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3986 .deviceId(mouseDeviceId)
3987 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3988 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3989 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003990
3991 spyWindow->consumeMotionEvent(
3992 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3993 spyWindow->consumeMotionEvent(
3994 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3996
Prabir Pradhan678438e2023-04-13 19:32:51 +00003997 mDispatcher->notifyMotion(
3998 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3999 .deviceId(mouseDeviceId)
4000 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4001 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4003 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004004 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4005 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4006
4007 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00004008 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4009 .deviceId(mouseDeviceId)
4010 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4011 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4012 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004013 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4014 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4015
4016 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00004017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4018 .deviceId(touchDeviceId)
4019 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4020 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004021
4022 // No more events
4023 spyWindow->assertNoEvents();
4024 window->assertNoEvents();
4025}
4026
4027/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004028 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
4029 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
4030 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
4031 * While the mouse is down, new move events from the touch device should continue to work.
4032 */
4033TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
4034 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004036 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4037 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004038 spyWindow->setFrame(Rect(0, 0, 200, 200));
4039 spyWindow->setTrustedOverlay(true);
4040 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004041 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4042 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004043 window->setFrame(Rect(0, 0, 200, 200));
4044
4045 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4046
4047 const int32_t mouseDeviceId = 7;
4048 const int32_t touchDeviceId = 4;
4049
4050 // Hover a bit with mouse first
4051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4052 .deviceId(mouseDeviceId)
4053 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4054 .build());
4055 spyWindow->consumeMotionEvent(
4056 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4057 window->consumeMotionEvent(
4058 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4059
4060 // Start touching
4061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4062 .deviceId(touchDeviceId)
4063 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4064 .build());
4065
4066 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4067 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4068
4069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4070 .deviceId(touchDeviceId)
4071 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
4072 .build());
4073 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4074 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4075
4076 // Pilfer the stream
4077 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4078 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
4079 // Hover is not pilfered! Only touch.
4080
4081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4082 .deviceId(touchDeviceId)
4083 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
4084 .build());
4085 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4086
4087 // Mouse down
4088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4089 .deviceId(mouseDeviceId)
4090 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4091 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4092 .build());
4093
4094 spyWindow->consumeMotionEvent(
4095 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4096 spyWindow->consumeMotionEvent(
4097 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4098 window->consumeMotionEvent(
4099 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4100 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4101
4102 mDispatcher->notifyMotion(
4103 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4104 .deviceId(mouseDeviceId)
4105 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4106 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4107 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4108 .build());
4109 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4110 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4111
4112 // Mouse move!
4113 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4114 .deviceId(mouseDeviceId)
4115 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4116 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4117 .build());
4118 spyWindow->consumeMotionEvent(
4119 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4120 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4121
4122 // Touch move!
4123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4124 .deviceId(touchDeviceId)
4125 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4126 .build());
4127 spyWindow->consumeMotionEvent(
4128 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4129
4130 // No more events
4131 spyWindow->assertNoEvents();
4132 window->assertNoEvents();
4133}
4134
4135/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004136 * On the display, have a single window, and also an area where there's no window.
4137 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4138 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4139 */
4140TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4142 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004143 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004144
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004145 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004146
4147 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004148 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004149
4150 mDispatcher->waitForIdle();
4151 window->assertNoEvents();
4152
4153 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004154 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004155 mDispatcher->waitForIdle();
4156 window->consumeMotionDown();
4157}
4158
4159/**
4160 * Same test as above, but instead of touching the empty space, the first touch goes to
4161 * non-touchable window.
4162 */
4163TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4164 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4165 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004166 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004167 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4168 window1->setTouchable(false);
4169 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004170 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004171 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4172
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004173 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004174
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004175 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004176 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004177
4178 mDispatcher->waitForIdle();
4179 window1->assertNoEvents();
4180 window2->assertNoEvents();
4181
4182 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004183 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004184 mDispatcher->waitForIdle();
4185 window2->consumeMotionDown();
4186}
4187
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004188/**
4189 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4190 * to the event time of the first ACTION_DOWN sent to the particular window.
4191 */
4192TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4194 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004195 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004196 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4197 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004198 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004199 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4200
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004201 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004202
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004203 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004204 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004205 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004206
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004207 const std::unique_ptr<MotionEvent> firstDown =
4208 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4209 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004210 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004211
4212 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004213 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004214 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004215
4216 const std::unique_ptr<MotionEvent> secondDown =
4217 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4218 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4219 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4220 // We currently send MOVE events to all windows receiving a split touch when there is any change
4221 // in the touch state, even when none of the pointers in the split window actually moved.
4222 // Document this behavior in the test.
4223 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004224
4225 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004226 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004227 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004228
4229 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4230 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004231
4232 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004233 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004234 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004235
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004236 window2->consumeMotionEvent(
4237 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4238 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004239
4240 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004241 mDispatcher->notifyMotion(
4242 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004243 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004244
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004245 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4246 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4247
4248 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004249 mDispatcher->notifyMotion(
4250 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004251 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004252
4253 window1->consumeMotionEvent(
4254 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4255 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004256}
4257
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004258/**
4259 * When events are not split, the downTime should be adjusted such that the downTime corresponds
4260 * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
4261 * the event routing because the first window prevents splitting.
4262 */
4263TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004264 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4266 sp<FakeWindowHandle> window1 =
4267 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4268 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4269 window1->setPreventSplitting(true);
4270
4271 sp<FakeWindowHandle> window2 =
4272 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4273 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4274
4275 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4276
4277 // Touch down on the first window
4278 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4279 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4280 .build();
4281 mDispatcher->notifyMotion(downArgs);
4282
4283 window1->consumeMotionEvent(
4284 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4285
4286 // Second window is added
4287 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4288
4289 // Now touch down on the window with another pointer
4290 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4291 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4292 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4293 .downTime(downArgs.downTime)
4294 .build());
4295 window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4296
4297 // Finish the gesture
4298 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4299 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4300 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4301 .downTime(downArgs.downTime)
4302 .build());
4303 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4304 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4305 .downTime(downArgs.downTime)
4306 .build());
4307 window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4308 window1->consumeMotionEvent(
4309 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4310 window2->assertNoEvents();
4311}
4312
4313/**
4314 * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4315 * to the event time of the first ACTION_DOWN sent to the new window.
4316 * If a new window that does not support split appears on the screen and gets touched with the
4317 * second finger, it should not get any events because it doesn't want split touches. At the same
4318 * time, the first window should not get the pointer_down event because it supports split touches
4319 * (and the touch occurred outside of the bounds of window1).
4320 */
4321TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004322 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4324 sp<FakeWindowHandle> window1 =
4325 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4326 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4327
4328 sp<FakeWindowHandle> window2 =
4329 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4330 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4331
4332 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4333
4334 // Touch down on the first window
4335 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4336 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4337 .build();
4338 mDispatcher->notifyMotion(downArgs);
4339
4340 window1->consumeMotionEvent(
4341 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4342
4343 // Second window is added
4344 window2->setPreventSplitting(true);
4345 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4346
4347 // Now touch down on the window with another pointer
4348 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4349 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4350 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4351 .downTime(downArgs.downTime)
4352 .build());
4353 // Event is dropped because window2 doesn't support split touch, and window1 does.
4354
4355 // Complete the gesture
4356 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4357 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4358 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4359 .downTime(downArgs.downTime)
4360 .build());
4361 // A redundant MOVE event is generated that doesn't carry any new information
4362 window1->consumeMotionEvent(
4363 AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4365 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4366 .downTime(downArgs.downTime)
4367 .build());
4368
4369 window1->consumeMotionEvent(
4370 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4371 window1->assertNoEvents();
4372 window2->assertNoEvents();
4373}
4374
Garfield Tandf26e862020-07-01 20:18:19 -07004375TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004377 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4378 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004379 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004380 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4381 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004382 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004383
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004384 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004385
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004386 mDispatcher->onWindowInfosChanged(
4387 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004388
4389 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004391 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004392 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4393 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004394 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004395 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004396 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004397
4398 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004399 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004400 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004401 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4402 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004403 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004404 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004405 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4406 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004407
4408 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004409 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004410 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004411 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4412 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004414 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004415 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4416 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004417
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004419 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004420 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4421 AINPUT_SOURCE_MOUSE)
4422 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4423 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004424 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004425 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004426 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004427
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004428 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004429 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004430 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4431 AINPUT_SOURCE_MOUSE)
4432 .buttonState(0)
4433 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004434 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004435 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004436 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004437
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004438 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004439 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004440 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4441 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004442 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004443 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004444 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004445
4446 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004447 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004448 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004449 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4450 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004451 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004452 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004453 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004454
4455 // No more events
4456 windowLeft->assertNoEvents();
4457 windowRight->assertNoEvents();
4458}
4459
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004460/**
4461 * Put two fingers down (and don't release them) and click the mouse button.
4462 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4463 * currently active gesture should be canceled, and the new one should proceed.
4464 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004465TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4466 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004468 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4469 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004470 window->setFrame(Rect(0, 0, 600, 800));
4471
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004472 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004473
4474 const int32_t touchDeviceId = 4;
4475 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004476
4477 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004478 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4479 .deviceId(touchDeviceId)
4480 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4481 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004482
Prabir Pradhan678438e2023-04-13 19:32:51 +00004483 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4484 .deviceId(touchDeviceId)
4485 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4486 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4487 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004488 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4489 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4490
4491 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4493 .deviceId(mouseDeviceId)
4494 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4495 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4496 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004497 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4498 WithPointerCount(2u)));
4499 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4500
Prabir Pradhan678438e2023-04-13 19:32:51 +00004501 mDispatcher->notifyMotion(
4502 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4503 .deviceId(mouseDeviceId)
4504 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4505 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4506 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4507 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004508 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4509
4510 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4511 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4513 .deviceId(touchDeviceId)
4514 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4515 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4516 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004517 window->assertNoEvents();
4518}
4519
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004520/**
4521 * Put two fingers down (and don't release them) and click the mouse button.
4522 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4523 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4524 */
4525TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4526 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004528 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4529 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004530 window->setFrame(Rect(0, 0, 600, 800));
4531
4532 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4533
4534 const int32_t touchDeviceId = 4;
4535 const int32_t mouseDeviceId = 6;
4536
4537 // Two pointers down
4538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4539 .deviceId(touchDeviceId)
4540 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4541 .build());
4542
4543 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4544 .deviceId(touchDeviceId)
4545 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4546 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4547 .build());
4548 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4549 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4550
4551 // Send a series of mouse events for a mouse click
4552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4553 .deviceId(mouseDeviceId)
4554 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4555 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4556 .build());
4557 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4558
4559 mDispatcher->notifyMotion(
4560 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4561 .deviceId(mouseDeviceId)
4562 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4563 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4564 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4565 .build());
4566 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4567
4568 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4569 // already active gesture, it should be sent normally.
4570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4571 .deviceId(touchDeviceId)
4572 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4573 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4574 .build());
4575 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4576 window->assertNoEvents();
4577}
4578
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004579/**
4580 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4581 * though the window underneath should not get any events.
4582 */
4583TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
4584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4585
4586 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4587 ui::LogicalDisplayId::DEFAULT);
4588 spyWindow->setFrame(Rect(0, 0, 100, 100));
4589 spyWindow->setTrustedOverlay(true);
4590 spyWindow->setPreventSplitting(true);
4591 spyWindow->setSpy(true);
4592 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4593 sp<FakeWindowHandle> inputSinkWindow =
4594 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4595 ui::LogicalDisplayId::DEFAULT);
4596 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4597 inputSinkWindow->setTrustedOverlay(true);
4598 inputSinkWindow->setPreventSplitting(true);
4599 inputSinkWindow->setNoInputChannel(true);
4600
4601 mDispatcher->onWindowInfosChanged(
4602 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4603
4604 // Tap the spy window
4605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4606 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4607 .build());
4608 mDispatcher->notifyMotion(
4609 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4610 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4611 .build());
4612
4613 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4614 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4615 inputSinkWindow->assertNoEvents();
4616}
4617
4618/**
4619 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4620 * though the window underneath should not get any events.
4621 * Same test as above, but with two pointers touching instead of one.
4622 */
4623TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
4624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4625
4626 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4627 ui::LogicalDisplayId::DEFAULT);
4628 spyWindow->setFrame(Rect(0, 0, 100, 100));
4629 spyWindow->setTrustedOverlay(true);
4630 spyWindow->setPreventSplitting(true);
4631 spyWindow->setSpy(true);
4632 // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4633 sp<FakeWindowHandle> inputSinkWindow =
4634 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4635 ui::LogicalDisplayId::DEFAULT);
4636 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4637 inputSinkWindow->setTrustedOverlay(true);
4638 inputSinkWindow->setPreventSplitting(true);
4639 inputSinkWindow->setNoInputChannel(true);
4640
4641 mDispatcher->onWindowInfosChanged(
4642 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4643
4644 // Both fingers land into the spy window
4645 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4646 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4647 .build());
4648 mDispatcher->notifyMotion(
4649 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4650 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4651 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4652 .build());
4653 mDispatcher->notifyMotion(
4654 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4655 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4656 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4657 .build());
4658 mDispatcher->notifyMotion(
4659 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4660 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4661 .build());
4662
4663 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4664 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4665 spyWindow->consumeMotionPointerUp(1, WithPointerCount(2));
4666 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4667 inputSinkWindow->assertNoEvents();
4668}
4669
4670/** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
4671class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
4672 public ::testing::WithParamInterface<bool> {
4673};
4674
4675/**
4676 * Three windows:
4677 * - An application window (app window)
4678 * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
4679 * - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
4680 *
4681 * The spy window is side-by-side with the app window. The inputSink is below the spy.
4682 * We first touch the area outside of the appWindow, but inside spyWindow.
4683 * Only the SPY window should get the DOWN event.
4684 * The spy pilfers after receiving the first DOWN event.
4685 * Next, we touch the app window.
4686 * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
4687 * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
4688 * pointers automatically, as well.
4689 * Next, the first pointer (from the spy) is lifted.
4690 * Spy should get POINTER_UP(0).
4691 * This event should not go to the app because the app never received this pointer to begin with.
4692 * Now, lift the remaining pointer and check that the spy receives UP event.
4693 *
4694 * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
4695 * This test attempts to reproduce a crash in the dispatcher.
4696 */
4697TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004698 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4700
4701 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4702 ui::LogicalDisplayId::DEFAULT);
4703 spyWindow->setFrame(Rect(100, 100, 200, 200));
4704 spyWindow->setTrustedOverlay(true);
4705 spyWindow->setPreventSplitting(true);
4706 spyWindow->setSpy(true);
4707 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4708 sp<FakeWindowHandle> inputSinkWindow =
4709 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4710 ui::LogicalDisplayId::DEFAULT);
4711 inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
4712 inputSinkWindow->setTrustedOverlay(true);
4713 inputSinkWindow->setPreventSplitting(GetParam());
4714 inputSinkWindow->setNoInputChannel(true);
4715
4716 sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
4717 ui::LogicalDisplayId::DEFAULT);
4718 appWindow->setFrame(Rect(0, 0, 100, 100));
4719
4720 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4721 mDispatcher->onWindowInfosChanged(
4722 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo(), *appWindow->getInfo()},
4723 {},
4724 0,
4725 0});
4726
4727 // First finger lands outside of the appWindow, but inside of the spy window
4728 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4729 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4730 .build());
4731 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4732
4733 mDispatcher->pilferPointers(spyWindow->getToken());
4734
4735 // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
4736 // the spy is already pilfering the first pointer, and this automatically grants the remaining
4737 // new pointers to the spy, as well.
4738 mDispatcher->notifyMotion(
4739 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4740 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4741 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4742 .build());
4743
4744 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4745
4746 // Now lift up the first pointer
4747 mDispatcher->notifyMotion(
4748 MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
4749 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4750 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4751 .build());
4752 spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
4753
4754 // And lift the remaining pointer!
4755 mDispatcher->notifyMotion(
4756 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4757 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4758 .build());
4759 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
4760
4761 // Now send a new DOWN, which should again go to spy.
4762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4763 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4764 .build());
4765 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4766 // The app window doesn't get any events this entire time because the spy received the events
4767 // first and pilfered, which makes all new pointers go to it as well.
4768 appWindow->assertNoEvents();
4769}
4770
4771// Behaviour should be the same regardless of whether inputSink supports splitting.
4772INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
4773 SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
4774
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004775TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4777
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004778 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4779 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004780 spyWindow->setFrame(Rect(0, 0, 600, 800));
4781 spyWindow->setTrustedOverlay(true);
4782 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004783 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4784 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004785 window->setFrame(Rect(0, 0, 600, 800));
4786
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004787 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004788 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004789
4790 // Send mouse cursor to the window
4791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004792 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004793 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4794 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004795 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004796 .build()));
4797
4798 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4799 WithSource(AINPUT_SOURCE_MOUSE)));
4800 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4801 WithSource(AINPUT_SOURCE_MOUSE)));
4802
4803 window->assertNoEvents();
4804 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004805}
4806
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004807TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4808 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004809 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4810
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004811 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4812 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004813 spyWindow->setFrame(Rect(0, 0, 600, 800));
4814 spyWindow->setTrustedOverlay(true);
4815 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004816 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4817 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004818 window->setFrame(Rect(0, 0, 600, 800));
4819
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004820 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004821 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004822
4823 // Send mouse cursor to the window
4824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004825 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004826 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4827 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004828 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004829 .build()));
4830
4831 // Move mouse cursor
4832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004833 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004834 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4835 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004836 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004837 .build()));
4838
4839 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4840 WithSource(AINPUT_SOURCE_MOUSE)));
4841 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4842 WithSource(AINPUT_SOURCE_MOUSE)));
4843 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4844 WithSource(AINPUT_SOURCE_MOUSE)));
4845 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4846 WithSource(AINPUT_SOURCE_MOUSE)));
4847 // Touch down on the window
4848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004849 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004850 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4851 AINPUT_SOURCE_TOUCHSCREEN)
4852 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004853 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004854 .build()));
4855 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4856 WithSource(AINPUT_SOURCE_MOUSE)));
4857 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4858 WithSource(AINPUT_SOURCE_MOUSE)));
4859 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4860 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4861 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4862 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4863
4864 // pilfer the motion, retaining the gesture on the spy window.
4865 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4866 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4867 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4868
4869 // Touch UP on the window
4870 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004871 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004872 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4873 AINPUT_SOURCE_TOUCHSCREEN)
4874 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004875 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004876 .build()));
4877 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4878 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4879
4880 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4881 // to send a new gesture. It should again go to both windows (spy and the window below), just
4882 // like the first gesture did, before pilfering. The window configuration has not changed.
4883
4884 // One more tap - DOWN
4885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004886 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004887 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4888 AINPUT_SOURCE_TOUCHSCREEN)
4889 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004890 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004891 .build()));
4892 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4893 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4894 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4895 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4896
4897 // Touch UP on the window
4898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004899 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004900 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4901 AINPUT_SOURCE_TOUCHSCREEN)
4902 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004903 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004904 .build()));
4905 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4906 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4907 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4908 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4909
4910 window->assertNoEvents();
4911 spyWindow->assertNoEvents();
4912}
4913
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004914TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4915 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4917
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004918 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4919 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004920 spyWindow->setFrame(Rect(0, 0, 600, 800));
4921 spyWindow->setTrustedOverlay(true);
4922 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004923 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4924 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004925 window->setFrame(Rect(0, 0, 600, 800));
4926
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004927 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004928 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4929
4930 // Send mouse cursor to the window
4931 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4932 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4933 .build());
4934
4935 // Move mouse cursor
4936 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4937 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4938 .build());
4939
4940 window->consumeMotionEvent(
4941 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4942 spyWindow->consumeMotionEvent(
4943 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4944 window->consumeMotionEvent(
4945 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4946 spyWindow->consumeMotionEvent(
4947 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4948 // Touch down on the window
4949 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4950 .deviceId(SECOND_DEVICE_ID)
4951 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4952 .build());
4953 window->consumeMotionEvent(
4954 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4955 spyWindow->consumeMotionEvent(
4956 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4957
4958 // pilfer the motion, retaining the gesture on the spy window.
4959 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4960 window->consumeMotionEvent(
4961 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4962 // Mouse hover is not pilfered
4963
4964 // Touch UP on the window
4965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4966 .deviceId(SECOND_DEVICE_ID)
4967 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4968 .build());
4969 spyWindow->consumeMotionEvent(
4970 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4971
4972 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4973 // to send a new gesture. It should again go to both windows (spy and the window below), just
4974 // like the first gesture did, before pilfering. The window configuration has not changed.
4975
4976 // One more tap - DOWN
4977 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4978 .deviceId(SECOND_DEVICE_ID)
4979 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4980 .build());
4981 window->consumeMotionEvent(
4982 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4983 spyWindow->consumeMotionEvent(
4984 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4985
4986 // Touch UP on the window
4987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4988 .deviceId(SECOND_DEVICE_ID)
4989 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4990 .build());
4991 window->consumeMotionEvent(
4992 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4993 spyWindow->consumeMotionEvent(
4994 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4995
4996 // Mouse movement continues normally as well
4997 // Move mouse cursor
4998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
5000 .build());
5001 window->consumeMotionEvent(
5002 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
5003 spyWindow->consumeMotionEvent(
5004 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
5005
5006 window->assertNoEvents();
5007 spyWindow->assertNoEvents();
5008}
5009
Garfield Tandf26e862020-07-01 20:18:19 -07005010// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
5011// directly in this test.
5012TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07005013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005014 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5015 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07005016 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07005017
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005018 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07005019
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005020 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07005021
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005023 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005024 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5025 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005026 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005027 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005028 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07005029 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005031 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005032 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5033 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005034 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005035 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08005036 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5037 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07005038
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005040 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005041 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
5042 AINPUT_SOURCE_MOUSE)
5043 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
5044 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005045 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005046 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005047 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07005048
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005050 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005051 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
5052 AINPUT_SOURCE_MOUSE)
5053 .buttonState(0)
5054 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005055 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005056 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005057 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07005058
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005060 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005061 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
5062 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005063 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005064 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005065 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07005066
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07005067 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
5068 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
5069 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005070 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07005071 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
5072 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005073 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07005074 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08005075 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07005076}
5077
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005078/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005079 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
5080 * is generated.
5081 */
5082TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
5083 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005084 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5085 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005086 window->setFrame(Rect(0, 0, 1200, 800));
5087
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005088 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005090 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005091
5092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005093 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005094 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5095 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005096 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005097 .build()));
5098 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5099
5100 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005101 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005102 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
5103}
5104
5105/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07005106 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
5107 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00005108TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
5109 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
5110 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07005111 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005112 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5113 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005114 window->setFrame(Rect(0, 0, 1200, 800));
5115
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005116 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005117
5118 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5119
5120 MotionEventBuilder hoverEnterBuilder =
5121 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5122 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5123 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5125 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5127 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5128 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5129 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5130}
5131
5132/**
Siarhei Vishniakou9d0d65e2024-08-02 12:10:05 -07005133 * Invalid events injected by input filter are rejected.
5134 */
5135TEST_F(InputDispatcherTest, InvalidA11yEventsGetRejected) {
5136 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5137 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5138 ui::LogicalDisplayId::DEFAULT);
5139
5140 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5141
5142 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5143
5144 // a11y sets 'POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY' policy flag during injection, so define
5145 // a custom injection function here for convenience.
5146 auto injectFromAccessibility = [&](int32_t action, float x, float y) {
5147 MotionEvent event = MotionEventBuilder(action, AINPUT_SOURCE_TOUCHSCREEN)
5148 .pointer(PointerBuilder(0, ToolType::FINGER).x(x).y(y))
5149 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT)
5150 .build();
5151 return injectMotionEvent(*mDispatcher, event, 100ms,
5152 InputEventInjectionSync::WAIT_FOR_RESULT, /*targetUid=*/{},
5153 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_FILTERED |
5154 POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY);
5155 };
5156
5157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5158 injectFromAccessibility(ACTION_DOWN, /*x=*/300, /*y=*/400));
5159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5160 injectFromAccessibility(ACTION_MOVE, /*x=*/310, /*y=*/420));
5161 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5162 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5163 // finger is still down, so a new DOWN event should be rejected!
5164 ASSERT_EQ(InputEventInjectionResult::FAILED,
5165 injectFromAccessibility(ACTION_DOWN, /*x=*/340, /*y=*/410));
5166
5167 // if the gesture is correctly finished, new down event will succeed
5168 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5169 injectFromAccessibility(ACTION_MOVE, /*x=*/320, /*y=*/430));
5170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5171 injectFromAccessibility(ACTION_UP, /*x=*/320, /*y=*/430));
5172 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5173 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5174
5175 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5176 injectFromAccessibility(ACTION_DOWN, /*x=*/350, /*y=*/460));
5177 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5178}
5179
5180/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005181 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
5182 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005183TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
5184 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005186 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5187 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005188 window->setFrame(Rect(0, 0, 100, 100));
5189
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005190 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005191
5192 const int32_t mouseDeviceId = 7;
5193 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005194
5195 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00005196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5197 .deviceId(mouseDeviceId)
5198 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5199 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005200 window->consumeMotionEvent(
5201 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5202
5203 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00005204 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5205 .deviceId(touchDeviceId)
5206 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5207 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005208
5209 window->consumeMotionEvent(
5210 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
5211 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5212}
5213
5214/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005215 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
5216 */
5217TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
5218 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005220 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5221 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005222 window->setFrame(Rect(0, 0, 100, 100));
5223
5224 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5225
5226 const int32_t mouseDeviceId = 7;
5227 const int32_t touchDeviceId = 4;
5228
5229 // Start hovering with the mouse
5230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5231 .deviceId(mouseDeviceId)
5232 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5233 .build());
5234 window->consumeMotionEvent(
5235 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5236
5237 // Touch goes down
5238 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5239 .deviceId(touchDeviceId)
5240 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5241 .build());
5242 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5243}
5244
5245/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005246 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005247 * The tap causes a HOVER_EXIT event to be generated because the current event
5248 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005249 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005250TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
5251 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005253 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5254 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005255 window->setFrame(Rect(0, 0, 100, 100));
5256
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005257 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005258 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5259 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5260 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005261 ASSERT_NO_FATAL_FAILURE(
5262 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5263 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005264
5265 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005266 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5267 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5268 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005269 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005270 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5271 WithSource(AINPUT_SOURCE_MOUSE))));
5272
5273 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005274 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5275 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5276
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005277 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5278 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5279 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005280 ASSERT_NO_FATAL_FAILURE(
5281 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5282 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5283}
5284
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005285/**
5286 * Send a mouse hover event followed by a tap from touchscreen.
5287 * The tap causes a HOVER_EXIT event to be generated because the current event
5288 * stream's source has been switched.
5289 */
5290TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
5291 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005293 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5294 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005295 window->setFrame(Rect(0, 0, 100, 100));
5296
5297 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5299 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5300 .build());
5301
5302 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5303 WithSource(AINPUT_SOURCE_MOUSE)));
5304
5305 // Tap on the window
5306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5307 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5308 .build());
5309
5310 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5311 WithSource(AINPUT_SOURCE_MOUSE)));
5312
5313 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5314 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5315
5316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5317 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5318 .build());
5319
5320 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5321 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5322}
5323
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005324TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
5325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5326 sp<FakeWindowHandle> windowDefaultDisplay =
5327 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005328 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005329 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
5330 sp<FakeWindowHandle> windowSecondDisplay =
5331 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
5332 SECOND_DISPLAY_ID);
5333 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
5334
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005335 mDispatcher->onWindowInfosChanged(
5336 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005337
5338 // Set cursor position in window in default display and check that hover enter and move
5339 // events are generated.
5340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005341 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005342 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5343 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005344 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005345 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005346 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005347 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005348
5349 // Remove all windows in secondary display and check that no event happens on window in
5350 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005351 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5352
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005353 windowDefaultDisplay->assertNoEvents();
5354
5355 // Move cursor position in window in default display and check that only hover move
5356 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005357 mDispatcher->onWindowInfosChanged(
5358 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005359 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005360 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005361 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5362 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005363 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005364 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005365 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005366 windowDefaultDisplay->consumeMotionEvent(
5367 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5368 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005369 windowDefaultDisplay->assertNoEvents();
5370}
5371
Garfield Tan00f511d2019-06-12 16:55:40 -07005372TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005373 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005374
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005375 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5376 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005377 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005378 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5379 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005380 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005381
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005382 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005383
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005384 mDispatcher->onWindowInfosChanged(
5385 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005386
5387 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5388 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005390 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005391 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5392 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005393 windowRight->assertNoEvents();
5394}
5395
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005396TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005398 sp<FakeWindowHandle> window =
5399 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5400 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005401 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005402
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005403 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005404 setFocusedWindow(window);
5405
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005406 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005407
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005408 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005409
5410 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005411 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005412
5413 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5414 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005415 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005416 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005417}
5418
5419TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005421 sp<FakeWindowHandle> window =
5422 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5423 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005424
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005425 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005426
Prabir Pradhan678438e2023-04-13 19:32:51 +00005427 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005428 AINPUT_SOURCE_TOUCHSCREEN,
5429 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005430
5431 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005432 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005433
5434 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5435 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005436 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005437 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005438 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005439}
5440
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005441TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5442 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005443 sp<FakeWindowHandle> window =
5444 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5445 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005447 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005448
5449 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5450 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5451 .build());
5452
5453 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5454
5455 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5456 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5457 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5458
5459 // After the device has been reset, a new hovering stream can be sent to the window
5460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5461 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5462 .build());
5463 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5464}
5465
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005466TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005468 sp<FakeWindowHandle> window =
5469 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5470 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005471 window->setFocusable(true);
5472
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005473 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005474 setFocusedWindow(window);
5475
5476 window->consumeFocusEvent(true);
5477
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005478 const NotifyKeyArgs keyArgs =
5479 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005480 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5481 const nsecs_t injectTime = keyArgs.eventTime;
5482 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005483 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005484 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005485 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005486 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5487 std::chrono::nanoseconds(interceptKeyTimeout).count());
5488}
5489
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005490/**
5491 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5492 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005493TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005495 sp<FakeWindowHandle> window =
5496 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5497 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005498 window->setFocusable(true);
5499
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005500 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005501 setFocusedWindow(window);
5502
5503 window->consumeFocusEvent(true);
5504
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005505 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5506 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005507
5508 // Set a value that's significantly larger than the default consumption timeout. If the
5509 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5510 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005511 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005512 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005513 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005514}
5515
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005516/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005517 * Two windows. First is a regular window. Second does not overlap with the first, and has
5518 * WATCH_OUTSIDE_TOUCH.
5519 * Both windows are owned by the same UID.
5520 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5521 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5522 */
5523TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005525 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5526 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005527 window->setFrame(Rect{0, 0, 100, 100});
5528
5529 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005530 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005531 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005532 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5533 outsideWindow->setWatchOutsideTouch(true);
5534 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005535 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005536
5537 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005538 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005539 AINPUT_SOURCE_TOUCHSCREEN,
5540 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005541 window->consumeMotionDown();
5542 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5543 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5544 outsideWindow->consumeMotionEvent(
5545 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005546
5547 // Ensure outsideWindow doesn't get any more events for the gesture.
5548 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005549 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005550 window->consumeMotionMove();
5551 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005552}
5553
5554/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005555 * Three windows:
5556 * - Left window
5557 * - Right window
5558 * - Outside window(watch for ACTION_OUTSIDE events)
5559 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5560 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5561 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5562 *
5563 * First, device A report a down event landed in the right window, the outside window can receive
5564 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5565 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5566 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5567 * window can receive it, but outside window event can't receive it.
5568 */
5569TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5571 sp<FakeWindowHandle> leftWindow =
5572 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005573 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005574 leftWindow->setFrame(Rect{0, 0, 100, 100});
5575 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5576
5577 sp<FakeWindowHandle> outsideWindow =
5578 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005579 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005580 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5581 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5582 outsideWindow->setWatchOutsideTouch(true);
5583
5584 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5585 std::make_shared<FakeApplicationHandle>();
5586 sp<FakeWindowHandle> rightWindow =
5587 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005588 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005589 rightWindow->setFrame(Rect{100, 0, 200, 100});
5590 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5591
5592 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5593 // when left window or right window is tapped
5594 mDispatcher->onWindowInfosChanged(
5595 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5596 {},
5597 0,
5598 0});
5599
5600 const DeviceId deviceA = 9;
5601 const DeviceId deviceB = 3;
5602
5603 // Tap on right window use device A
5604 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5605 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5606 .deviceId(deviceA)
5607 .build());
5608 leftWindow->assertNoEvents();
5609 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5610 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5611 // with zeroed coords.
5612 outsideWindow->consumeMotionEvent(
5613 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5614
5615 // Tap on left window use device B
5616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5617 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5618 .deviceId(deviceB)
5619 .build());
5620 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5621 rightWindow->assertNoEvents();
5622 // Because new gesture down on the left window that has the same owner with outside Window, the
5623 // outside Window should receive the ACTION_OUTSIDE with coords.
5624 outsideWindow->consumeMotionEvent(
5625 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5626
5627 // Ensure that windows that can only accept outside do not receive remaining gestures
5628 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5629 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5630 .deviceId(deviceA)
5631 .build());
5632 leftWindow->assertNoEvents();
5633 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5634
5635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5636 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5637 .deviceId(deviceB)
5638 .build());
5639 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5640 rightWindow->assertNoEvents();
5641 outsideWindow->assertNoEvents();
5642}
5643
5644/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005645 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5646 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5647 * ACTION_OUTSIDE event is sent per gesture.
5648 */
5649TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5650 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5651 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005652 sp<FakeWindowHandle> window =
5653 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5654 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005655 window->setWatchOutsideTouch(true);
5656 window->setFrame(Rect{0, 0, 100, 100});
5657 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005658 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005659 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005660 secondWindow->setFrame(Rect{100, 100, 200, 200});
5661 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005662 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005663 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005664 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005665 mDispatcher->onWindowInfosChanged(
5666 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005667
5668 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005669 mDispatcher->notifyMotion(
5670 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5671 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005672 window->assertNoEvents();
5673 secondWindow->assertNoEvents();
5674
5675 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5676 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005677 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005678 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005679 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005680 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5681 window->consumeMotionEvent(
5682 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005683 secondWindow->consumeMotionDown();
5684 thirdWindow->assertNoEvents();
5685
5686 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5687 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005688 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005689 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5690 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005691 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005692 window->assertNoEvents();
5693 secondWindow->consumeMotionMove();
5694 thirdWindow->consumeMotionDown();
5695}
5696
Prabir Pradhan814fe082022-07-22 20:22:18 +00005697TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005699 sp<FakeWindowHandle> window =
5700 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5701 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005702 window->setFocusable(true);
5703
Patrick Williamsd828f302023-04-28 17:52:08 -05005704 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005705 setFocusedWindow(window);
5706
5707 window->consumeFocusEvent(true);
5708
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005709 const NotifyKeyArgs keyDown =
5710 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5711 const NotifyKeyArgs keyUp =
5712 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005713 mDispatcher->notifyKey(keyDown);
5714 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005715
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005716 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5717 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005718
5719 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005720 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005721
5722 window->consumeFocusEvent(false);
5723
Prabir Pradhan678438e2023-04-13 19:32:51 +00005724 mDispatcher->notifyKey(keyDown);
5725 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005726 window->assertNoEvents();
5727}
5728
Arthur Hung96483742022-11-15 03:30:48 +00005729TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005730 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Arthur Hung96483742022-11-15 03:30:48 +00005731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005732 sp<FakeWindowHandle> window =
5733 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5734 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005735 // Ensure window is non-split and have some transform.
5736 window->setPreventSplitting(true);
5737 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005739
5740 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005741 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5742 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005743 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005744 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005745
5746 const MotionEvent secondFingerDownEvent =
5747 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005748 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005749 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005750 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5751 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005752 .build();
5753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005754 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005755 InputEventInjectionSync::WAIT_FOR_RESULT))
5756 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5757
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005758 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5759 ASSERT_NE(nullptr, event);
5760 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5761 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5762 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5763 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5764 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005765}
5766
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005767/**
5768 * Two windows: a splittable and a non-splittable.
5769 * The non-splittable window shouldn't receive any "incomplete" gestures.
5770 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5771 * The second pointer should be dropped because the initial window is splittable, so it won't get
5772 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5773 * "incomplete" gestures.
5774 */
5775TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005776 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5778 sp<FakeWindowHandle> leftWindow =
5779 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005780 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005781 leftWindow->setPreventSplitting(false);
5782 leftWindow->setFrame(Rect(0, 0, 100, 100));
5783 sp<FakeWindowHandle> rightWindow =
5784 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005785 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005786 rightWindow->setPreventSplitting(true);
5787 rightWindow->setFrame(Rect(100, 100, 200, 200));
5788 mDispatcher->onWindowInfosChanged(
5789 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5790
5791 // Touch down on left, splittable window
5792 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5793 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5794 .build());
5795 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5796
5797 mDispatcher->notifyMotion(
5798 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5799 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5800 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5801 .build());
5802 leftWindow->assertNoEvents();
5803 rightWindow->assertNoEvents();
5804}
5805
Siarhei Vishniakou27fc9f12024-07-13 23:59:47 -07005806/**
Siarhei Vishniakoufe346982024-08-07 00:17:19 +00005807 * Three windows:
5808 * 1) A window on the left, with flag dup_to_wallpaper
5809 * 2) A window on the right, with flag slippery
5810 * 3) A wallpaper window under the left window
5811 * When touch slips from right window to left, the wallpaper should receive a similar slippery
5812 * enter event. Later on, when another device becomes active, the wallpaper should receive
5813 * consistent streams from the new device, and also from the old device.
5814 * This test attempts to reproduce a crash in the dispatcher where the wallpaper target's downTime
5815 * was not getting set during slippery entrance.
5816 */
5817TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch) {
5818 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5819 std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5820 std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5821 std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5822 sp<FakeWindowHandle> wallpaper =
5823 sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5824 ui::LogicalDisplayId::DEFAULT);
5825 wallpaper->setIsWallpaper(true);
5826 wallpaper->setPreventSplitting(true);
5827 wallpaper->setTouchable(false);
5828
5829 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5830 ui::LogicalDisplayId::DEFAULT);
5831 leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5832 leftWindow->setDupTouchToWallpaper(true);
5833
5834 sp<FakeWindowHandle> rightWindow =
5835 sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5836 ui::LogicalDisplayId::DEFAULT);
5837 rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5838 rightWindow->setSlippery(true);
5839 rightWindow->setWatchOutsideTouch(true);
5840 rightWindow->setTrustedOverlay(true);
5841
5842 mDispatcher->onWindowInfosChanged(
5843 {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5844
5845 const DeviceId deviceA = 3;
5846 const DeviceId deviceB = 9;
5847
5848 // First finger from device A into right window
5849 NotifyMotionArgs deviceADownArgs =
5850 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5851 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5852 .deviceId(deviceA)
5853 .build();
5854
5855 mDispatcher->notifyMotion(deviceADownArgs);
5856 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5857
5858 // Move the finger of device A from right window into left window. It should slip.
5859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5860 .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5861 .deviceId(deviceA)
5862 .downTime(deviceADownArgs.downTime)
5863 .build());
5864
5865 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5866 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
5867 wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5868
5869 // Finger from device B down into left window
5870 NotifyMotionArgs deviceBDownArgs =
5871 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5872 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5873 .deviceId(deviceB)
5874 .build();
5875 mDispatcher->notifyMotion(deviceBDownArgs);
5876 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5877 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5878
5879 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
5880
5881 // Move finger from device B, still keeping it in the left window
5882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5883 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5884 .deviceId(deviceB)
5885 .downTime(deviceBDownArgs.downTime)
5886 .build());
5887 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5888 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5889
5890 // Lift the finger from device B
5891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5892 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5893 .deviceId(deviceB)
5894 .downTime(deviceBDownArgs.downTime)
5895 .build());
5896 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5897 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5898
5899 // Move the finger of device A, keeping it in the left window
5900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5901 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5902 .deviceId(deviceA)
5903 .downTime(deviceADownArgs.downTime)
5904 .build());
5905
5906 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5907 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5908
5909 // Second finger down from device A, into the right window. It should be split into:
5910 // MOVE for the left window (due to existing implementation) + a DOWN into the right window
5911 // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
5912 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5913 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5914 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5915 .deviceId(deviceA)
5916 .downTime(deviceADownArgs.downTime)
5917 .build());
5918 auto firstFingerMoveFromDeviceA = AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE),
5919 WithPointerCount(1), WithPointerId(0, 0));
5920 leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5921 wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5922 rightWindow->consumeMotionEvent(
5923 AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
5924
5925 // Lift up the second finger.
5926 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5927 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5928 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5929 .deviceId(deviceA)
5930 .downTime(deviceADownArgs.downTime)
5931 .build());
5932
5933 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5934 leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5935 wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5936
5937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5938 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5939 .deviceId(deviceA)
5940 .downTime(deviceADownArgs.downTime)
5941 .build());
5942
5943 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5944 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5945 rightWindow->assertNoEvents();
5946}
5947
5948/**
5949 * Same test as above, but with enable_multi_device_same_window_stream flag set to false.
5950 */
5951TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch_legacy) {
5952 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
5953 std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5954 std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5955 std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5956 sp<FakeWindowHandle> wallpaper =
5957 sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5958 ui::LogicalDisplayId::DEFAULT);
5959 wallpaper->setIsWallpaper(true);
5960 wallpaper->setPreventSplitting(true);
5961 wallpaper->setTouchable(false);
5962
5963 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5964 ui::LogicalDisplayId::DEFAULT);
5965 leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5966 leftWindow->setDupTouchToWallpaper(true);
5967
5968 sp<FakeWindowHandle> rightWindow =
5969 sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5970 ui::LogicalDisplayId::DEFAULT);
5971 rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5972 rightWindow->setSlippery(true);
5973 rightWindow->setWatchOutsideTouch(true);
5974 rightWindow->setTrustedOverlay(true);
5975
5976 mDispatcher->onWindowInfosChanged(
5977 {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5978
5979 const DeviceId deviceA = 3;
5980 const DeviceId deviceB = 9;
5981
5982 // First finger from device A into right window
5983 NotifyMotionArgs deviceADownArgs =
5984 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5985 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5986 .deviceId(deviceA)
5987 .build();
5988
5989 mDispatcher->notifyMotion(deviceADownArgs);
5990 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5991
5992 // Move the finger of device A from right window into left window. It should slip.
5993 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5994 .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5995 .deviceId(deviceA)
5996 .downTime(deviceADownArgs.downTime)
5997 .build());
5998
5999 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6000 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6001 wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6002
6003 // Finger from device B down into left window
6004 NotifyMotionArgs deviceBDownArgs =
6005 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6006 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6007 .deviceId(deviceB)
6008 .build();
6009 mDispatcher->notifyMotion(deviceBDownArgs);
6010 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
6011 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
6012 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
6013 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
6014
6015 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
6016
6017 // Move finger from device B, still keeping it in the left window
6018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6019 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
6020 .deviceId(deviceB)
6021 .downTime(deviceBDownArgs.downTime)
6022 .build());
6023 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
6024 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
6025
6026 // Lift the finger from device B
6027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6028 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
6029 .deviceId(deviceB)
6030 .downTime(deviceBDownArgs.downTime)
6031 .build());
6032 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
6033 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
6034
6035 // Move the finger of device A, keeping it in the left window
6036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6037 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6038 .deviceId(deviceA)
6039 .downTime(deviceADownArgs.downTime)
6040 .build());
6041 // This device was already canceled, so MOVE events will not be arriving to the windows from it.
6042
6043 // Second finger down from device A, into the right window. It should be split into:
6044 // MOVE for the left window (due to existing implementation) + a DOWN into the right window
6045 // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
6046 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6047 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6048 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
6049 .deviceId(deviceA)
6050 .downTime(deviceADownArgs.downTime)
6051 .build());
6052 rightWindow->consumeMotionEvent(
6053 AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
6054
6055 // Lift up the second finger.
6056 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6057 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6058 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
6059 .deviceId(deviceA)
6060 .downTime(deviceADownArgs.downTime)
6061 .build());
6062
6063 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
6064
6065 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6066 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
6067 .deviceId(deviceA)
6068 .downTime(deviceADownArgs.downTime)
6069 .build());
6070 rightWindow->assertNoEvents();
6071}
6072
6073/**
Siarhei Vishniakou27fc9f12024-07-13 23:59:47 -07006074 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
6075 * down event to the right window. Device B sends a down event to the left window, and then a
6076 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
6077 * POINTER_DOWN event should only go to the left window, and not to the right window.
6078 * This test attempts to reproduce a crash.
6079 */
6080TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07006081 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou27fc9f12024-07-13 23:59:47 -07006082 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6083 sp<FakeWindowHandle> leftWindow =
6084 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
6085 ui::LogicalDisplayId::DEFAULT);
6086 leftWindow->setFrame(Rect(0, 0, 100, 100));
6087 leftWindow->setPreventSplitting(true);
6088
6089 sp<FakeWindowHandle> rightWindow =
6090 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
6091 ui::LogicalDisplayId::DEFAULT);
6092 rightWindow->setFrame(Rect(100, 0, 200, 100));
6093
6094 mDispatcher->onWindowInfosChanged(
6095 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
6096
6097 const DeviceId deviceA = 9;
6098 const DeviceId deviceB = 3;
6099 // Touch the right window with device A
6100 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6101 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6102 .deviceId(deviceA)
6103 .build());
6104 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
6105 // Touch the left window with device B
6106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6107 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6108 .deviceId(deviceB)
6109 .build());
6110 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
6111 // Send a second pointer from device B to the right window. It shouldn't go to the right window
6112 // because the left window prevents splitting.
6113 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6114 .deviceId(deviceB)
6115 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6116 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6117 .build());
6118 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
6119
6120 // Finish the gesture for both devices
6121 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6122 .deviceId(deviceB)
6123 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6124 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6125 .build());
6126 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
6127 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6128 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6129 .deviceId(deviceB)
6130 .build());
6131 leftWindow->consumeMotionEvent(
6132 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
6133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6134 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6135 .deviceId(deviceA)
6136 .build());
6137 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
6138}
6139
Harry Cuttsb166c002023-05-09 13:06:05 +00006140TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
6141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6143 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006144 window->setFrame(Rect(0, 0, 400, 400));
6145 sp<FakeWindowHandle> trustedOverlay =
6146 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006147 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006148 trustedOverlay->setSpy(true);
6149 trustedOverlay->setTrustedOverlay(true);
6150
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006151 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00006152
6153 // Start a three-finger touchpad swipe
6154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6155 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6156 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6157 .build());
6158 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6159 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6160 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6161 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6162 .build());
6163 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6164 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6165 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6166 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6167 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6168 .build());
6169
6170 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6171 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6172 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
6173
6174 // Move the swipe a bit
6175 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6176 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6177 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6178 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6179 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6180 .build());
6181
6182 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6183
6184 // End the swipe
6185 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6186 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6187 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6188 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6189 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6190 .build());
6191 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6192 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6193 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6194 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6195 .build());
6196 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6197 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6198 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6199 .build());
6200
6201 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
6202 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6203 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
6204
6205 window->assertNoEvents();
6206}
6207
6208TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
6209 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006210 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6211 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006212 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006213 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00006214
6215 // Start a three-finger touchpad swipe
6216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6217 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6218 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6219 .build());
6220 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6221 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6222 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6223 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6224 .build());
6225 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6226 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6227 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6228 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6229 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6230 .build());
6231
6232 // Move the swipe a bit
6233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6234 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6235 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6236 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6237 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6238 .build());
6239
6240 // End the swipe
6241 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6242 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6243 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6244 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6245 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6246 .build());
6247 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6248 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6249 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6250 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6251 .build());
6252 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6253 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6254 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6255 .build());
6256
6257 window->assertNoEvents();
6258}
6259
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00006260/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006261 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
6262 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006263 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006264 */
6265TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
6266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006267 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6268 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006269 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006270 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006271
6272 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
6273 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6274 .downTime(baseTime + 10)
6275 .eventTime(baseTime + 10)
6276 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6277 .build());
6278
6279 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6280
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006281 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006282 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006283
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006285
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006286 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6287 .downTime(baseTime + 10)
6288 .eventTime(baseTime + 30)
6289 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6290 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6291 .build());
6292
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006293 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6294
6295 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006296 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6297 .downTime(baseTime + 10)
6298 .eventTime(baseTime + 40)
6299 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6300 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6301 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006302
6303 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6304
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6306 .downTime(baseTime + 10)
6307 .eventTime(baseTime + 50)
6308 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6309 .build());
6310
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006311 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
6312
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6314 .downTime(baseTime + 60)
6315 .eventTime(baseTime + 60)
6316 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6317 .build());
6318
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006319 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006320}
6321
6322/**
Hu Guo771a7692023-09-17 20:51:08 +08006323 * When there are multiple screens, such as screen projection to TV or screen recording, if the
6324 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
6325 * its coordinates should be converted by the transform of the windows of target screen.
6326 */
6327TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
6328 // This case will create a window and a spy window on the default display and mirror
6329 // window on the second display. cancel event is sent through spy window pilferPointers
6330 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6331
6332 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006333 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6334 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08006335 spyWindowDefaultDisplay->setTrustedOverlay(true);
6336 spyWindowDefaultDisplay->setSpy(true);
6337
6338 sp<FakeWindowHandle> windowDefaultDisplay =
6339 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006340 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08006341 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
6342
6343 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
6344 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
6345
6346 // Add the windows to the dispatcher
6347 mDispatcher->onWindowInfosChanged(
6348 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
6349 *windowSecondDisplay->getInfo()},
6350 {},
6351 0,
6352 0});
6353
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006354 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08006355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006356 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6357 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08006358 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6359
6360 spyWindowDefaultDisplay->consumeMotionDown();
6361 windowDefaultDisplay->consumeMotionDown();
6362
6363 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
6364
6365 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006366 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
6367 ASSERT_NE(nullptr, event);
6368 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08006369
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006370 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
6371 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
6372 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
6373 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006374 EXPECT_EQ(100, event->getX(0));
6375 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08006376}
6377
6378/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006379 * Ensure the correct coordinate spaces are used by InputDispatcher.
6380 *
6381 * InputDispatcher works in the display space, so its coordinate system is relative to the display
6382 * panel. Windows get events in the window space, and get raw coordinates in the logical display
6383 * space.
6384 */
6385class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
6386public:
6387 void SetUp() override {
6388 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006389 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006390 }
6391
Linnan Li13bf76a2024-05-05 19:18:02 +08006392 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006393 gui::DisplayInfo info;
6394 info.displayId = displayId;
6395 info.transform = transform;
6396 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05006397 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006398 }
6399
6400 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
6401 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05006402 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006403 }
6404
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006405 void removeAllWindowsAndDisplays() {
6406 mDisplayInfos.clear();
6407 mWindowInfos.clear();
6408 }
6409
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006410 // Set up a test scenario where the display has a scaled projection and there are two windows
6411 // on the display.
6412 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
6413 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
6414 // respectively.
6415 ui::Transform displayTransform;
6416 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006417 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006418
6419 std::shared_ptr<FakeApplicationHandle> application =
6420 std::make_shared<FakeApplicationHandle>();
6421
6422 // Add two windows to the display. Their frames are represented in the display space.
6423 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006424 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006425 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006426 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
6427 addWindow(firstWindow);
6428
6429 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006430 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006431 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006432 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
6433 addWindow(secondWindow);
6434 return {std::move(firstWindow), std::move(secondWindow)};
6435 }
6436
6437private:
6438 std::vector<gui::DisplayInfo> mDisplayInfos;
6439 std::vector<gui::WindowInfo> mWindowInfos;
6440};
6441
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006442TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006443 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6444 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006445 // selected so that if the hit test was performed with the point and the bounds being in
6446 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006447 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006448 AINPUT_SOURCE_TOUCHSCREEN,
6449 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006450
6451 firstWindow->consumeMotionDown();
6452 secondWindow->assertNoEvents();
6453}
6454
6455// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
6456// the event should be treated as being in the logical display space.
6457TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
6458 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6459 // Send down to the first window. The point is represented in the logical display space. The
6460 // point is selected so that if the hit test was done in logical display space, then it would
6461 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006462 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006463 PointF{75 * 2, 55 * 4});
6464
6465 firstWindow->consumeMotionDown();
6466 secondWindow->assertNoEvents();
6467}
6468
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006469// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
6470// event should be treated as being in the logical display space.
6471TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
6472 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6473
6474 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6475 ui::Transform injectedEventTransform;
6476 injectedEventTransform.set(matrix);
6477 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
6478 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
6479
6480 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006481 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006482 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006483 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006484 .x(untransformedPoint.x)
6485 .y(untransformedPoint.y))
6486 .build();
6487 event.transform(matrix);
6488
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006489 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006490 InputEventInjectionSync::WAIT_FOR_RESULT);
6491
6492 firstWindow->consumeMotionDown();
6493 secondWindow->assertNoEvents();
6494}
6495
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006496TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
6497 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6498
6499 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006500 mDispatcher->notifyMotion(
6501 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6502 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006503
6504 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006505 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
6506 ASSERT_NE(nullptr, event);
6507 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006508
6509 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006510 EXPECT_EQ(300, event->getRawX(0));
6511 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006512
6513 // Ensure that the x and y values are in the window's coordinate space.
6514 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
6515 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006516 EXPECT_EQ(100, event->getX(0));
6517 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006518}
6519
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006520TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
6521 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6522 // The monitor will always receive events in the logical display's coordinate space, because
6523 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006524 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006525
6526 // Send down to the first window.
6527 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006528 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006529 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6530 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6531
6532 // Second pointer goes down on second window.
6533 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006534 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006535 {PointF{50, 100}, PointF{150, 220}}));
6536 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
6537 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
6538 {1, PointF{300, 880}}};
6539 monitor.consumeMotionEvent(
6540 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
6541
6542 mDispatcher->cancelCurrentTouch();
6543
6544 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6545 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
6546 monitor.consumeMotionEvent(
6547 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
6548}
6549
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006550TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
6551 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6552
6553 // Send down to the first window.
6554 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006555 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006556 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6557
6558 // The pointer is transferred to the second window, and the second window receives it in the
6559 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006560 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006561 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6562 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
6563}
6564
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006565TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
6566 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6567
6568 // Send hover move to the second window, and ensure it shows up as hover enter.
6569 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006570 ui::LogicalDisplayId::DEFAULT,
6571 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006572 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6573 WithCoords(100, 80), WithRawCoords(300, 880)));
6574
6575 // Touch down at the same location and ensure a hover exit is synthesized.
6576 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006577 ui::LogicalDisplayId::DEFAULT,
6578 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006579 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6580 WithRawCoords(300, 880)));
6581 secondWindow->consumeMotionEvent(
6582 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6583 secondWindow->assertNoEvents();
6584 firstWindow->assertNoEvents();
6585}
6586
Prabir Pradhan453ae732023-10-13 14:30:14 +00006587// Same as above, but while the window is being mirrored.
6588TEST_F(InputDispatcherDisplayProjectionTest,
6589 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
6590 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6591
6592 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6593 ui::Transform secondDisplayTransform;
6594 secondDisplayTransform.set(matrix);
6595 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6596
6597 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6598 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6599 addWindow(secondWindowClone);
6600
6601 // Send hover move to the second window, and ensure it shows up as hover enter.
6602 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006603 ui::LogicalDisplayId::DEFAULT,
6604 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006605 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6606 WithCoords(100, 80), WithRawCoords(300, 880)));
6607
6608 // Touch down at the same location and ensure a hover exit is synthesized for the correct
6609 // display.
6610 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006611 ui::LogicalDisplayId::DEFAULT,
6612 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006613 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6614 WithRawCoords(300, 880)));
6615 secondWindow->consumeMotionEvent(
6616 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6617 secondWindow->assertNoEvents();
6618 firstWindow->assertNoEvents();
6619}
6620
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006621TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6622 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6623
6624 // Send hover enter to second window
6625 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006626 ui::LogicalDisplayId::DEFAULT,
6627 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006628 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6629 WithCoords(100, 80), WithRawCoords(300, 880)));
6630
6631 mDispatcher->cancelCurrentTouch();
6632
6633 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6634 WithRawCoords(300, 880)));
6635 secondWindow->assertNoEvents();
6636 firstWindow->assertNoEvents();
6637}
6638
Prabir Pradhan453ae732023-10-13 14:30:14 +00006639// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00006640TEST_F(InputDispatcherDisplayProjectionTest,
6641 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6642 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6643
6644 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6645 ui::Transform secondDisplayTransform;
6646 secondDisplayTransform.set(matrix);
6647 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6648
6649 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6650 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6651 addWindow(secondWindowClone);
6652
6653 // Send hover enter to second window
6654 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006655 ui::LogicalDisplayId::DEFAULT,
6656 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00006657 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6658 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006659 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006660
6661 mDispatcher->cancelCurrentTouch();
6662
6663 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6664 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6665 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006666 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006667 secondWindow->assertNoEvents();
6668 firstWindow->assertNoEvents();
6669}
6670
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006671/** Ensure consistent behavior of InputDispatcher in all orientations. */
6672class InputDispatcherDisplayOrientationFixture
6673 : public InputDispatcherDisplayProjectionTest,
6674 public ::testing::WithParamInterface<ui::Rotation> {};
6675
6676// This test verifies the touchable region of a window for all rotations of the display by tapping
6677// in different locations on the display, specifically points close to the four corners of a
6678// window.
6679TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6680 constexpr static int32_t displayWidth = 400;
6681 constexpr static int32_t displayHeight = 800;
6682
6683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6684
6685 const auto rotation = GetParam();
6686
6687 // Set up the display with the specified rotation.
6688 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6689 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6690 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6691 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6692 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006693 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006694
6695 // Create a window with its bounds determined in the logical display.
6696 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6697 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006698 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6699 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006700 window->setFrame(frameInDisplay, displayTransform);
6701 addWindow(window);
6702
6703 // The following points in logical display space should be inside the window.
6704 static const std::array<vec2, 4> insidePoints{
6705 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6706 for (const auto pointInsideWindow : insidePoints) {
6707 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6708 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006709 mDispatcher->notifyMotion(
6710 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6711 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006712 window->consumeMotionDown();
6713
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006714 mDispatcher->notifyMotion(
6715 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6716 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006717 window->consumeMotionUp();
6718 }
6719
6720 // The following points in logical display space should be outside the window.
6721 static const std::array<vec2, 5> outsidePoints{
6722 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6723 for (const auto pointOutsideWindow : outsidePoints) {
6724 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6725 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006726 mDispatcher->notifyMotion(
6727 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6728 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006729
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006730 mDispatcher->notifyMotion(
6731 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6732 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006733 }
6734 window->assertNoEvents();
6735}
6736
Linnan Li5e5645e2024-03-05 14:43:05 +00006737// This test verifies the occlusion detection for all rotations of the display by tapping
6738// in different locations on the display, specifically points close to the four corners of a
6739// window.
6740TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6741 constexpr static int32_t displayWidth = 400;
6742 constexpr static int32_t displayHeight = 800;
6743
6744 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6745 std::make_shared<FakeApplicationHandle>();
6746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6747
6748 const auto rotation = GetParam();
6749
6750 // Set up the display with the specified rotation.
6751 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6752 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6753 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6754 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6755 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006756 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006757
6758 // Create a window that not trusted.
6759 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6760
6761 const Rect untrustedWindowFrameInDisplay =
6762 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6763
6764 sp<FakeWindowHandle> untrustedWindow =
6765 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006766 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006767 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6768 untrustedWindow->setTrustedOverlay(false);
6769 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6770 untrustedWindow->setTouchable(false);
6771 untrustedWindow->setAlpha(1.0f);
6772 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6773 addWindow(untrustedWindow);
6774
6775 // Create a simple app window below the untrusted window.
6776 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6777 const Rect simpleAppWindowFrameInDisplay =
6778 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6779
6780 sp<FakeWindowHandle> simpleAppWindow =
6781 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006782 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006783 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6784 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6785 addWindow(simpleAppWindow);
6786
6787 // The following points in logical display space should be inside the untrusted window, so
6788 // the simple window could not receive events that coordinate is these point.
6789 static const std::array<vec2, 4> untrustedPoints{
6790 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6791
6792 for (const auto untrustedPoint : untrustedPoints) {
6793 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6794 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006795 mDispatcher->notifyMotion(
6796 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6797 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6798 mDispatcher->notifyMotion(
6799 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6800 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006801 }
6802 untrustedWindow->assertNoEvents();
6803 simpleAppWindow->assertNoEvents();
6804 // The following points in logical display space should be outside the untrusted window, so
6805 // the simple window should receive events that coordinate is these point.
6806 static const std::array<vec2, 5> trustedPoints{
6807 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6808 for (const auto trustedPoint : trustedPoints) {
6809 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6810 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006811 mDispatcher->notifyMotion(
6812 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6813 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6814 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006815 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006816 mDispatcher->notifyMotion(
6817 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6818 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6819 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006820 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6821 }
6822 untrustedWindow->assertNoEvents();
6823}
6824
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006825// Run the precision tests for all rotations.
6826INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6827 InputDispatcherDisplayOrientationFixture,
6828 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6829 ui::ROTATION_270),
6830 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6831 return ftl::enum_string(testParamInfo.param);
6832 });
6833
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006834using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6835 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006836
6837class TransferTouchFixture : public InputDispatcherTest,
6838 public ::testing::WithParamInterface<TransferFunction> {};
6839
6840TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006842
6843 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006844 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006845 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006846 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006847 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006848 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006849 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006850 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006851 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006852 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6853 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006854 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006855 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006856 mDispatcher->onWindowInfosChanged(
6857 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006858 setFocusedWindow(firstWindow);
6859 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006860
6861 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006862 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006863 AINPUT_SOURCE_TOUCHSCREEN,
6864 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006865
Svet Ganov5d3bc372020-01-26 23:11:07 -08006866 // Only the first window should get the down event
6867 firstWindow->consumeMotionDown();
6868 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006869 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006870 // Dispatcher reports pointer down outside focus for the wallpaper
6871 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006872
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006873 // Transfer touch to the second window
6874 TransferFunction f = GetParam();
6875 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6876 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006877 // The first window gets cancel and the second gets down
6878 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006879 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6880 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6881 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006882 // There should not be any changes to the focused window when transferring touch
6883 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006884
6885 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006886 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006887 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006888 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006889 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006890 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6891 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006892 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006893}
6894
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006895/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006896 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6897 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6898 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006899 * natural to the user.
6900 * In this test, we are sending a pointer to both spy window and first window. We then try to
6901 * transfer touch to the second window. The dispatcher should identify the first window as the
6902 * one that should lose the gesture, and therefore the action should be to move the gesture from
6903 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006904 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6905 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006906 */
6907TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6908 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6909
6910 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006911 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6912 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006913 spyWindow->setTrustedOverlay(true);
6914 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006915 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6916 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006917 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006918 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6919 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006920
6921 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006922 mDispatcher->onWindowInfosChanged(
6923 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006924
6925 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006926 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006927 AINPUT_SOURCE_TOUCHSCREEN,
6928 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006929 // Only the first window and spy should get the down event
6930 spyWindow->consumeMotionDown();
6931 firstWindow->consumeMotionDown();
6932
6933 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006934 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006935 TransferFunction f = GetParam();
6936 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6937 ASSERT_TRUE(success);
6938 // The first window gets cancel and the second gets down
6939 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006940 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6941 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006942
6943 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006944 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006945 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006946 // The first window gets no events and the second+spy get up
6947 firstWindow->assertNoEvents();
6948 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006949 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6950 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006951}
6952
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006953TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006955
6956 PointF touchPoint = {10, 10};
6957
6958 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006959 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006960 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006961 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006962 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006963 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006964 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006965 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006966 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006967
6968 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006969 mDispatcher->onWindowInfosChanged(
6970 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006971
6972 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006973 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006974 AINPUT_SOURCE_TOUCHSCREEN,
6975 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006976 // Only the first window should get the down event
6977 firstWindow->consumeMotionDown();
6978 secondWindow->assertNoEvents();
6979
6980 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006981 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006982 ui::LogicalDisplayId::DEFAULT,
6983 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006984 // Only the first window should get the pointer down event
6985 firstWindow->consumeMotionPointerDown(1);
6986 secondWindow->assertNoEvents();
6987
6988 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006989 TransferFunction f = GetParam();
6990 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6991 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006992 // The first window gets cancel and the second gets down and pointer down
6993 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006994 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6995 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6996 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006997 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006998
6999 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007000 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007001 ui::LogicalDisplayId::DEFAULT,
7002 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007003 // The first window gets nothing and the second gets pointer up
7004 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00007005 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7006 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7007 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7008 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007009
7010 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007011 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007012 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007013 // The first window gets nothing and the second gets up
7014 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007015 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7016 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007017}
7018
Arthur Hungc539dbb2022-12-08 07:45:36 +00007019TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
7020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7021
7022 // Create a couple of windows
7023 sp<FakeWindowHandle> firstWindow =
7024 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007025 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007026 firstWindow->setDupTouchToWallpaper(true);
7027 sp<FakeWindowHandle> secondWindow =
7028 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007029 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007030 secondWindow->setDupTouchToWallpaper(true);
7031
7032 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007033 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
7034 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007035 wallpaper1->setIsWallpaper(true);
7036
7037 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007038 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
7039 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007040 wallpaper2->setIsWallpaper(true);
7041 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007042 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
7043 *secondWindow->getInfo(), *wallpaper2->getInfo()},
7044 {},
7045 0,
7046 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00007047
7048 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007049 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007050 AINPUT_SOURCE_TOUCHSCREEN,
7051 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00007052
7053 // Only the first window should get the down event
7054 firstWindow->consumeMotionDown();
7055 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007056 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007057 wallpaper2->assertNoEvents();
7058
7059 // Transfer touch focus to the second window
7060 TransferFunction f = GetParam();
7061 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
7062 ASSERT_TRUE(success);
7063
7064 // The first window gets cancel and the second gets down
7065 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007066 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
7067 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7068 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
7069 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08007070 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007071
7072 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007073 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007074 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00007075 // The first window gets no events and the second gets up
7076 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007077 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7078 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007079 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007080 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08007081 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00007082}
7083
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007084// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00007085// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007086// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00007087INSTANTIATE_TEST_SUITE_P(
7088 InputDispatcherTransferFunctionTests, TransferTouchFixture,
7089 ::testing::Values(
7090 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
7091 sp<IBinder> destChannelToken) {
7092 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007093 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00007094 },
7095 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
7096 sp<IBinder> to) {
7097 return dispatcher->transferTouchGesture(from, to,
7098 /*isDragAndDrop=*/false);
7099 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007100
Prabir Pradhan367f3432024-02-13 23:05:58 +00007101TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07007102 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08007103
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007104 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007105 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007106 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007107 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007108
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007109 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007110 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007111 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007112 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007113
7114 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007115 mDispatcher->onWindowInfosChanged(
7116 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08007117
7118 PointF pointInFirst = {300, 200};
7119 PointF pointInSecond = {300, 600};
7120
7121 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007122 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007123 AINPUT_SOURCE_TOUCHSCREEN,
7124 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007125 // Only the first window should get the down event
7126 firstWindow->consumeMotionDown();
7127 secondWindow->assertNoEvents();
7128
7129 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007130 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007131 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007132 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007133 // The first window gets a move and the second a down
7134 firstWindow->consumeMotionMove();
7135 secondWindow->consumeMotionDown();
7136
Prabir Pradhan367f3432024-02-13 23:05:58 +00007137 // Transfer touch to the second window
7138 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08007139 // The first window gets cancel and the new gets pointer down (it already saw down)
7140 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007141 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007142 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007143
7144 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007145 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007146 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007147 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007148 // The first window gets nothing and the second gets pointer up
7149 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00007150 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7151 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7152 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7153 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007154
7155 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007156 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007157 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007158 // The first window gets nothing and the second gets up
7159 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007160 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7161 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007162}
7163
Prabir Pradhan367f3432024-02-13 23:05:58 +00007164// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
7165// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
7166// receiving touch is not supported, so the touch should continue on those windows and the
7167// transferred-to window should get nothing.
7168TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7170
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007171 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007172 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007173 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007174 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007175
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007176 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007177 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007178 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007179 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007180
7181 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007182 mDispatcher->onWindowInfosChanged(
7183 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007184
7185 PointF pointInFirst = {300, 200};
7186 PointF pointInSecond = {300, 600};
7187
7188 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007190 AINPUT_SOURCE_TOUCHSCREEN,
7191 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007192 // Only the first window should get the down event
7193 firstWindow->consumeMotionDown();
7194 secondWindow->assertNoEvents();
7195
7196 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007197 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007198 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007199 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007200 // The first window gets a move and the second a down
7201 firstWindow->consumeMotionMove();
7202 secondWindow->consumeMotionDown();
7203
7204 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007205 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
7206 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00007207 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007208 ASSERT_FALSE(transferred);
7209 firstWindow->assertNoEvents();
7210 secondWindow->assertNoEvents();
7211
7212 // The rest of the dispatch should proceed as normal
7213 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007214 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007215 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007216 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007217 // The first window gets MOVE and the second gets pointer up
7218 firstWindow->consumeMotionMove();
7219 secondWindow->consumeMotionUp();
7220
7221 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007222 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007223 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007224 // The first window gets nothing and the second gets up
7225 firstWindow->consumeMotionUp();
7226 secondWindow->assertNoEvents();
7227}
7228
Arthur Hungabbb9d82021-09-01 14:52:30 +00007229// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00007230// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00007231// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00007232TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00007233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7234 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007235 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7236 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007237 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007238 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007239 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7240 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007241 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007242
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007243 sp<FakeWindowHandle> mirrorWindowInPrimary =
7244 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007245 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007246
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007247 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007248 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007249
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007250 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007251 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007252
7253 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007254 mDispatcher->onWindowInfosChanged(
7255 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7256 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7257 *secondWindowInPrimary->getInfo()},
7258 {},
7259 0,
7260 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00007261
7262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7264 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7266
7267 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007268 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007269
Prabir Pradhan367f3432024-02-13 23:05:58 +00007270 // Transfer touch
7271 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
7272 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007273 // The first window gets cancel.
7274 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007275 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007276 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007277
7278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007279 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007280 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7282 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007283 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007284 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007285
7286 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007287 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00007288 {150, 50}))
7289 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7290 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007291 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7292 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007293}
7294
Prabir Pradhan367f3432024-02-13 23:05:58 +00007295// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
7296// 'transferTouchOnDisplay' api.
7297TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00007298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7299 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007300 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7301 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007302 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007303 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007304 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7305 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007306 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007307
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007308 sp<FakeWindowHandle> mirrorWindowInPrimary =
7309 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007310 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007311
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007312 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007313 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007314
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007315 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007316 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007317
7318 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007319 mDispatcher->onWindowInfosChanged(
7320 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7321 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7322 *secondWindowInPrimary->getInfo()},
7323 {},
7324 0,
7325 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00007326
7327 // Touch on second display.
7328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007329 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7330 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7332
7333 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007334 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007335
7336 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00007337 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
7338 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007339
7340 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007341 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00007342 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
7343 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007344
7345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007346 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00007347 SECOND_DISPLAY_ID, {150, 50}))
7348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007349 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00007350 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
7351 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007352
7353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007354 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007356 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00007357 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007358}
7359
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007360TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007361 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007362 sp<FakeWindowHandle> window =
7363 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7364 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007365
Vishnu Nair47074b82020-08-14 11:54:47 -07007366 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007367 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007368 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007369
7370 window->consumeFocusEvent(true);
7371
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007372 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007373
7374 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007375 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007376
7377 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007378 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00007379 mFakePolicy->assertUserActivityPoked();
7380}
7381
7382TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
7383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007384 sp<FakeWindowHandle> window =
7385 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7386 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007387
7388 window->setDisableUserActivity(true);
7389 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007390 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007391 setFocusedWindow(window);
7392
7393 window->consumeFocusEvent(true);
7394
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007395 mDispatcher->notifyKey(
7396 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007397
7398 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007399 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007400
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007401 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007402 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00007403 mFakePolicy->assertUserActivityNotPoked();
7404}
7405
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007406TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00007407 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007408 sp<FakeWindowHandle> window =
7409 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7410 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007411
7412 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007413 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007414 setFocusedWindow(window);
7415
7416 window->consumeFocusEvent(true);
7417
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007418 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7419
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007420 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007421 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007422 mDispatcher->waitForIdle();
7423
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007424 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00007425 window->assertNoEvents();
7426
7427 // Should have poked user activity
7428 mFakePolicy->assertUserActivityPoked();
7429}
7430
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007431TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00007432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007433 sp<FakeWindowHandle> window =
7434 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7435 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007436
7437 window->setDisableUserActivity(true);
7438 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007440 setFocusedWindow(window);
7441
7442 window->consumeFocusEvent(true);
7443
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007444 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7445
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007446 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007447 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007448 mDispatcher->waitForIdle();
7449
7450 // System key is not passed down
7451 window->assertNoEvents();
7452
7453 // Should have poked user activity
7454 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007455}
7456
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007457class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
7458 public ::testing::WithParamInterface<bool> {};
7459
7460TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
7461 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7462 sp<FakeWindowHandle> window =
7463 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7464 ui::LogicalDisplayId::DEFAULT);
7465
7466 window->setDisableUserActivity(GetParam());
7467
7468 window->setFocusable(true);
7469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7470 setFocusedWindow(window);
7471
7472 window->consumeFocusEvent(true);
7473
7474 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7475 .keyCode(AKEYCODE_A)
7476 .policyFlags(0)
7477 .build());
7478 mDispatcher->waitForIdle();
7479
7480 // Key is not passed down
7481 window->assertNoEvents();
7482
7483 // Should not have poked user activity
7484 mFakePolicy->assertUserActivityNotPoked();
7485}
7486
7487INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
7488 ::testing::Bool());
7489
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007490TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
7491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007492 sp<FakeWindowHandle> window =
7493 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7494 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007495
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007496 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007497
7498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007499 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007500 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007501 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7502
7503 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007504 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007505
7506 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007507 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007508 mFakePolicy->assertUserActivityPoked();
7509}
7510
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007511TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007513 sp<FakeWindowHandle> window =
7514 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7515 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007516
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007517 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007518
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007519 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007520 mDispatcher->waitForIdle();
7521
7522 window->assertNoEvents();
7523}
7524
7525// If a window is touchable, but does not have focus, it should receive motion events, but not keys
7526TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07007527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007528 sp<FakeWindowHandle> window =
7529 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7530 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007531
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007532 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007533
7534 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007535 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007536 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00007537 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007538 AINPUT_SOURCE_TOUCHSCREEN,
7539 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007540
7541 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007542 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007543 window->assertNoEvents(); // Key event or focus event will not be received
7544}
7545
arthurhungea3f4fc2020-12-21 23:18:53 +08007546TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
7547 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7548
arthurhungea3f4fc2020-12-21 23:18:53 +08007549 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007550 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007551 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007552 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08007553
arthurhungea3f4fc2020-12-21 23:18:53 +08007554 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007555 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007556 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007557 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08007558
7559 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007560 mDispatcher->onWindowInfosChanged(
7561 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08007562
7563 PointF pointInFirst = {300, 200};
7564 PointF pointInSecond = {300, 600};
7565
7566 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007567 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007568 AINPUT_SOURCE_TOUCHSCREEN,
7569 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007570 // Only the first window should get the down event
7571 firstWindow->consumeMotionDown();
7572 secondWindow->assertNoEvents();
7573
7574 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007575 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007576 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007577 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007578 // The first window gets a move and the second a down
7579 firstWindow->consumeMotionMove();
7580 secondWindow->consumeMotionDown();
7581
7582 // Send pointer cancel to the second window
7583 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007584 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7585 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08007586 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00007587 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08007588 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007589 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7590 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08007591
7592 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007593 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007594 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08007595 // The first window gets up and the second gets nothing.
7596 firstWindow->consumeMotionUp();
7597 secondWindow->assertNoEvents();
7598}
7599
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007600TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
7601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7602
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007603 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7604 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007605 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007606 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
7607 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
7608 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
7609
Harry Cutts33476232023-01-30 19:57:29 +00007610 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007611 window->assertNoEvents();
7612 mDispatcher->waitForIdle();
7613}
7614
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007615using InputDispatcherMonitorTest = InputDispatcherTest;
7616
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007617/**
7618 * Two entities that receive touch: A window, and a global monitor.
7619 * The touch goes to the window, and then the window disappears.
7620 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7621 * for the monitor, as well.
7622 * 1. foregroundWindow
7623 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7624 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007625TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007627 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7628 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007629
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007630 FakeMonitorReceiver monitor =
7631 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007632
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007633 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007635 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7636 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7638
7639 // Both the foreground window and the global monitor should receive the touch down
7640 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007641 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007642
7643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007644 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007645 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007646 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7647
7648 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007649 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007650
7651 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007652 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007653 window->consumeMotionCancel();
7654 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7655
7656 // If more events come in, there will be no more foreground window to send them to. This will
7657 // cause a cancel for the monitor, as well.
7658 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007659 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007660 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007661 << "Injection should fail because the window was removed";
7662 window->assertNoEvents();
7663 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007664 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007665}
7666
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007667TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07007668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007669 sp<FakeWindowHandle> window =
7670 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7671 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007672 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007673
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007674 FakeMonitorReceiver monitor =
7675 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007676
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007678 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7679 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007681 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7682 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007683}
7684
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007685TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007686 FakeMonitorReceiver monitor =
7687 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007688
Chris Yea209fde2020-07-22 13:54:51 -07007689 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007690 sp<FakeWindowHandle> window =
7691 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7692 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007693 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007694
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007696 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7697 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007699 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7700 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007701
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007702 // Pilfer pointers from the monitor.
7703 // This should not do anything and the window should continue to receive events.
7704 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007705
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007707 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007708 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007709 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007710
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007711 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7712 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007713}
7714
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007715TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007717 sp<FakeWindowHandle> window =
7718 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7719 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007720 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007721 window->setWindowOffset(20, 40);
7722 window->setWindowTransform(0, 1, -1, 0);
7723
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007724 FakeMonitorReceiver monitor =
7725 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007726
7727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007728 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7729 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007731 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007732 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7733 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007734 // Even though window has transform, gesture monitor must not.
7735 ASSERT_EQ(ui::Transform(), event->getTransform());
7736}
7737
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007738TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007740 FakeMonitorReceiver monitor =
7741 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007742
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007743 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007744 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7745 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007746 << "Injection should fail if there is a monitor, but no touchable window";
7747 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007748}
7749
Linnan Lid8150952024-01-26 18:07:17 +00007750/**
7751 * Two displays
7752 * The first monitor has a foreground window, a monitor
7753 * The second window has only one monitor.
7754 * We first inject a Down event into the first display, this injection should succeed and both
7755 * the foreground window and monitor should receive a down event, then inject a Down event into
7756 * the second display as well, this injection should fail, at this point, the first display
7757 * window and monitor should not receive a cancel or any other event.
7758 * Continue to inject Move and UP events to the first display, the events should be received
7759 * normally by the foreground window and monitor.
7760 */
7761TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007763 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7764 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007765
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007766 FakeMonitorReceiver monitor =
7767 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007768 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7769
7770 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007772 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7773 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007774 << "The down event injected into the first display should succeed";
7775
7776 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007777 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007778
7779 ASSERT_EQ(InputEventInjectionResult::FAILED,
7780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7781 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007782 << "The down event injected into the second display should fail since there's no "
7783 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007784
7785 // Continue to inject event to first display.
7786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7787 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007788 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007789 << "The move event injected into the first display should succeed";
7790
7791 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007792 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007793
7794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007795 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007796 {110, 220}))
7797 << "The up event injected into the first display should succeed";
7798
7799 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007800 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007801
7802 window->assertNoEvents();
7803 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007804 secondMonitor.assertNoEvents();
7805}
7806
7807/**
7808 * Two displays
7809 * There is a monitor and foreground window on each display.
7810 * First, we inject down events into each of the two displays, at this point, the foreground windows
7811 * and monitors on both displays should receive down events.
7812 * At this point, the foreground window of the second display goes away, the gone window should
7813 * receive the cancel event, and the other windows and monitors should not receive any events.
7814 * Inject a move event into the second display. At this point, the injection should fail because
7815 * the second display no longer has a foreground window. At this point, the monitor on the second
7816 * display should receive a cancel event, and any windows or monitors on the first display should
7817 * not receive any events, and any subsequent injection of events into the second display should
7818 * also fail.
7819 * Continue to inject events into the first display, and the events should all be injected
7820 * successfully and received normally.
7821 */
7822TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007824 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7825 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007826 sp<FakeWindowHandle> secondWindow =
7827 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7828 SECOND_DISPLAY_ID);
7829
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007830 FakeMonitorReceiver monitor =
7831 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007832 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7833
7834 // There is a foreground window on both displays.
7835 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7836 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007837 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7838 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007839 << "The down event injected into the first display should succeed";
7840
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007841 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7842 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007843
7844 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7845 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7846 {100, 200}))
7847 << "The down event injected into the second display should succeed";
7848
Linnan Lid8150952024-01-26 18:07:17 +00007849 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7850 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7851
7852 // Now second window is gone away.
7853 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7854
7855 // The gone window should receive a cancel, and the monitor on the second display should not
7856 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007857 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7858 secondMonitor.assertNoEvents();
7859
7860 ASSERT_EQ(InputEventInjectionResult::FAILED,
7861 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7862 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007863 << "The move event injected into the second display should fail because there's no "
7864 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007865 // Now the monitor on the second display should receive a cancel event.
7866 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007867
7868 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7869 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007870 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007871 << "The move event injected into the first display should succeed";
7872
7873 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007874 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007875
7876 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007877 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7878 {110, 220}))
7879 << "The up event injected into the second display should fail because there's no "
7880 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007881
7882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007883 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007884 {110, 220}))
7885 << "The up event injected into the first display should succeed";
7886
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007887 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7888 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007889
Linnan Lid8150952024-01-26 18:07:17 +00007890 window->assertNoEvents();
7891 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007892 secondWindow->assertNoEvents();
7893 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007894}
7895
7896/**
7897 * One display with transform
7898 * There is a foreground window and a monitor on the display
7899 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7900 * event and move event, then let the foreground window go away, the foreground window receives
7901 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7902 * by the monitor should be with the same transform as the display
7903 */
7904TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007906 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7907 ui::LogicalDisplayId::DEFAULT);
7908 FakeMonitorReceiver monitor =
7909 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007910
7911 ui::Transform transform;
7912 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7913
7914 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007915 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007916 displayInfo.transform = transform;
7917
7918 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7919
7920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007921 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7922 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007923 << "The down event injected should succeed";
7924
7925 window->consumeMotionDown();
7926 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7927 EXPECT_EQ(transform, downMotionEvent->getTransform());
7928 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7929
7930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7931 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007932 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007933 << "The move event injected should succeed";
7934
7935 window->consumeMotionMove();
7936 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7937 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7938 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7939
7940 // Let foreground window gone
7941 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7942
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007943 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007944 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007945
7946 ASSERT_EQ(InputEventInjectionResult::FAILED,
7947 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007948 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007949 << "The move event injected should failed";
7950 // Now foreground should not receive any events, but monitor should receive a cancel event
7951 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007952 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7953 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007954 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007955 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7956
7957 // Other event inject to this display should fail.
7958 ASSERT_EQ(InputEventInjectionResult::FAILED,
7959 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007960 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007961 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007962 window->assertNoEvents();
7963 monitor.assertNoEvents();
7964}
7965
chaviw81e2bb92019-12-18 15:03:51 -08007966TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007968 sp<FakeWindowHandle> window =
7969 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7970 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007971
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007972 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007973
7974 NotifyMotionArgs motionArgs =
7975 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007976 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007977
Prabir Pradhan678438e2023-04-13 19:32:51 +00007978 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007979 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007980 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007981
7982 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007983 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007984 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7985 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7986 motionArgs.pointerCoords[0].getX() - 10);
7987
Prabir Pradhan678438e2023-04-13 19:32:51 +00007988 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007989 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007990}
7991
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007992/**
7993 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7994 * the device default right away. In the test scenario, we check both the default value,
7995 * and the action of enabling / disabling.
7996 */
7997TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007999 sp<FakeWindowHandle> window =
8000 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8001 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08008002 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008003
8004 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008005 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008006 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008007
8008 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008009 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008010 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008011 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008012
8013 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07008014 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008015 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00008016 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008017
8018 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08008019 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008020 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008021 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07008022 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008023 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008024 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008025 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008026
8027 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07008028 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008029 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00008030 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008031
8032 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08008033 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008034 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00008035 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07008036 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008037 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008038 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00008039 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008040
8041 window->assertNoEvents();
8042}
8043
Gang Wange9087892020-01-07 12:17:14 -05008044TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07008045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008046 sp<FakeWindowHandle> window =
8047 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8048 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05008049
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008050 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07008051 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05008052
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008053 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008054 setFocusedWindow(window);
8055
Harry Cutts33476232023-01-30 19:57:29 +00008056 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05008057
Prabir Pradhan678438e2023-04-13 19:32:51 +00008058 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
8059 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05008060
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008061 std::unique_ptr<KeyEvent> event = window->consumeKey();
8062 ASSERT_NE(event, nullptr);
8063 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05008064 ASSERT_NE(verified, nullptr);
8065 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
8066
8067 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
8068 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
8069 ASSERT_EQ(keyArgs.source, verified->source);
8070 ASSERT_EQ(keyArgs.displayId, verified->displayId);
8071
8072 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
8073
8074 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05008075 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08008076 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05008077 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
8078 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
8079 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
8080 ASSERT_EQ(0, verifiedKey.repeatCount);
8081}
8082
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008083TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07008084 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008085 sp<FakeWindowHandle> window =
8086 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
8087 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008088
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008089 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008090
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008091 ui::Transform transform;
8092 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8093
8094 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008095 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008096 displayInfo.transform = transform;
8097
Patrick Williamsd828f302023-04-28 17:52:08 -05008098 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008099
Prabir Pradhan678438e2023-04-13 19:32:51 +00008100 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008101 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008102 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008103 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008104
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008105 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
8106 ASSERT_NE(nullptr, event);
8107 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008108 ASSERT_NE(verified, nullptr);
8109 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
8110
8111 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
8112 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
8113 EXPECT_EQ(motionArgs.source, verified->source);
8114 EXPECT_EQ(motionArgs.displayId, verified->displayId);
8115
8116 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
8117
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008118 const vec2 rawXY =
8119 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
8120 motionArgs.pointerCoords[0].getXYValue());
8121 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
8122 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008123 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008124 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08008125 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008126 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
8127 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
8128}
8129
chaviw09c8d2d2020-08-24 15:48:26 -07008130/**
8131 * Ensure that separate calls to sign the same data are generating the same key.
8132 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
8133 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
8134 * tests.
8135 */
8136TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
8137 KeyEvent event = getTestKeyEvent();
8138 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8139
8140 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
8141 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
8142 ASSERT_EQ(hmac1, hmac2);
8143}
8144
8145/**
8146 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
8147 */
8148TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
8149 KeyEvent event = getTestKeyEvent();
8150 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8151 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
8152
8153 verifiedEvent.deviceId += 1;
8154 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8155
8156 verifiedEvent.source += 1;
8157 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8158
8159 verifiedEvent.eventTimeNanos += 1;
8160 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8161
Linnan Li13bf76a2024-05-05 19:18:02 +08008162 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07008163 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8164
8165 verifiedEvent.action += 1;
8166 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8167
8168 verifiedEvent.downTimeNanos += 1;
8169 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8170
8171 verifiedEvent.flags += 1;
8172 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8173
8174 verifiedEvent.keyCode += 1;
8175 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8176
8177 verifiedEvent.scanCode += 1;
8178 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8179
8180 verifiedEvent.metaState += 1;
8181 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8182
8183 verifiedEvent.repeatCount += 1;
8184 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8185}
8186
Vishnu Nair958da932020-08-21 17:12:37 -07008187TEST_F(InputDispatcherTest, SetFocusedWindow) {
8188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008189 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8190 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008191 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008192 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8193 ui::LogicalDisplayId::DEFAULT);
8194 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008195
8196 // Top window is also focusable but is not granted focus.
8197 windowTop->setFocusable(true);
8198 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008199 mDispatcher->onWindowInfosChanged(
8200 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008201 setFocusedWindow(windowSecond);
8202
8203 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008204 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008205 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008206
8207 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008208 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008209 windowTop->assertNoEvents();
8210}
8211
8212TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
8213 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008214 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8215 ui::LogicalDisplayId::DEFAULT);
8216 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008217
8218 window->setFocusable(true);
8219 // Release channel for window is no longer valid.
8220 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008221 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008222 setFocusedWindow(window);
8223
8224 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008225 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07008226
8227 // window channel is invalid, so it should not receive any input event.
8228 window->assertNoEvents();
8229}
8230
8231TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
8232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008233 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8234 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008235 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008236 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008237
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008238 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008239 setFocusedWindow(window);
8240
8241 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008242 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07008243
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008244 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07008245 window->assertNoEvents();
8246}
8247
8248TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
8249 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008250 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8251 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008252 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008253 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8254 ui::LogicalDisplayId::DEFAULT);
8255 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008256
8257 windowTop->setFocusable(true);
8258 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008259 mDispatcher->onWindowInfosChanged(
8260 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008261 setFocusedWindow(windowTop);
8262 windowTop->consumeFocusEvent(true);
8263
Chavi Weingarten847e8512023-03-29 00:26:09 +00008264 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008265 mDispatcher->onWindowInfosChanged(
8266 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008267 windowSecond->consumeFocusEvent(true);
8268 windowTop->consumeFocusEvent(false);
8269
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008271 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008272
8273 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008274 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008275}
8276
Chavi Weingarten847e8512023-03-29 00:26:09 +00008277TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07008278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008279 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8280 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008281 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008282 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8283 ui::LogicalDisplayId::DEFAULT);
8284 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008285
8286 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00008287 windowSecond->setFocusable(false);
8288 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008289 mDispatcher->onWindowInfosChanged(
8290 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00008291 setFocusedWindow(windowTop);
8292 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07008293
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00008295 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008296
8297 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008298 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008299 windowSecond->assertNoEvents();
8300}
8301
8302TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
8303 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008304 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8305 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008306 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008307 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008308 ui::LogicalDisplayId::DEFAULT);
8309 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008310
8311 window->setFocusable(true);
8312 previousFocusedWindow->setFocusable(true);
8313 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008314 mDispatcher->onWindowInfosChanged(
8315 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008316 setFocusedWindow(previousFocusedWindow);
8317 previousFocusedWindow->consumeFocusEvent(true);
8318
8319 // Requesting focus on invisible window takes focus from currently focused window.
8320 setFocusedWindow(window);
8321 previousFocusedWindow->consumeFocusEvent(false);
8322
8323 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008325 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008326 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008327
8328 // Window does not get focus event or key down.
8329 window->assertNoEvents();
8330
8331 // Window becomes visible.
8332 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008333 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008334
8335 // Window receives focus event.
8336 window->consumeFocusEvent(true);
8337 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008338 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008339}
8340
Vishnu Nair599f1412021-06-21 10:39:58 -07008341TEST_F(InputDispatcherTest, DisplayRemoved) {
8342 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008343 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
8344 ui::LogicalDisplayId::DEFAULT);
8345 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07008346
8347 // window is granted focus.
8348 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008349 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07008350 setFocusedWindow(window);
8351 window->consumeFocusEvent(true);
8352
8353 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008354 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07008355 window->consumeFocusEvent(false);
8356}
8357
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008358/**
8359 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
8360 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
8361 * of the 'slipperyEnterWindow'.
8362 *
8363 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
8364 * a way so that the touched location is no longer covered by the top window.
8365 *
8366 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
8367 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
8368 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
8369 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
8370 * with ACTION_DOWN).
8371 * Thus, the touch has been transferred from the top window into the bottom window, because the top
8372 * window moved itself away from the touched location and had Flag::SLIPPERY.
8373 *
8374 * Even though the top window moved away from the touched location, it is still obscuring the bottom
8375 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
8376 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
8377 *
8378 * In this test, we ensure that the event received by the bottom window has
8379 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
8380 */
8381TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008382 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008383 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008384
8385 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008386 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008387
8388 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008389 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8390 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008391 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008392 // Make sure this one overlaps the bottom window
8393 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
8394 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
8395 // one. Windows with the same owner are not considered to be occluding each other.
8396 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
8397
8398 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008399 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8400 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008401 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
8402
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008403 mDispatcher->onWindowInfosChanged(
8404 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008405
8406 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00008407 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008408 AINPUT_SOURCE_TOUCHSCREEN,
8409 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008410 slipperyExitWindow->consumeMotionDown();
8411 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008412 mDispatcher->onWindowInfosChanged(
8413 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008414
Prabir Pradhan678438e2023-04-13 19:32:51 +00008415 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008416 AINPUT_SOURCE_TOUCHSCREEN,
8417 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008418
8419 slipperyExitWindow->consumeMotionCancel();
8420
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008421 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008422 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8423}
8424
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008425/**
8426 * Two windows, one on the left and another on the right. The left window is slippery. The right
8427 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
8428 * touch moves from the left window into the right window, the gesture should continue to go to the
8429 * left window. Touch shouldn't slip because the right window can't receive touches. This test
8430 * reproduces a crash.
8431 */
8432TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
8433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8434
8435 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008436 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8437 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008438 leftSlipperyWindow->setSlippery(true);
8439 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
8440
8441 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008442 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8443 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008444 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
8445 rightDropTouchesWindow->setDropInput(true);
8446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008447 mDispatcher->onWindowInfosChanged(
8448 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008449
8450 // Start touch in the left window
8451 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8452 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8453 .build());
8454 leftSlipperyWindow->consumeMotionDown();
8455
8456 // And move it into the right window
8457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8458 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8459 .build());
8460
8461 // Since the right window isn't eligible to receive input, touch does not slip.
8462 // The left window continues to receive the gesture.
8463 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8464 rightDropTouchesWindow->assertNoEvents();
8465}
8466
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008467/**
8468 * A single window is on screen first. Touch is injected into that window. Next, a second window
8469 * appears. Since the first window is slippery, touch will move from the first window to the second.
8470 */
8471TEST_F(InputDispatcherTest, InjectedTouchSlips) {
8472 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8473 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008474 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
8475 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008476 originalWindow->setFrame(Rect(0, 0, 200, 200));
8477 originalWindow->setSlippery(true);
8478
8479 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008480 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
8481 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008482 appearingWindow->setFrame(Rect(0, 0, 200, 200));
8483
8484 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
8485
8486 // Touch down on the original window
8487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8488 injectMotionEvent(*mDispatcher,
8489 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8490 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
8491 .build()));
8492 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8493
8494 // Now, a new window appears. This could be, for example, a notification shade that appears
8495 // after user starts to drag down on the launcher window.
8496 mDispatcher->onWindowInfosChanged(
8497 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
8498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8499 injectMotionEvent(*mDispatcher,
8500 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8501 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
8502 .build()));
8503 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8504 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8506 injectMotionEvent(*mDispatcher,
8507 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8508 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
8509 .build()));
8510 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8511
8512 originalWindow->assertNoEvents();
8513 appearingWindow->assertNoEvents();
8514}
8515
Linnan Li49b2b202024-04-12 12:46:40 +08008516/**
8517 * Three windows:
8518 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
8519 * - right window
8520 * - spy window
8521 * The three windows do not overlap.
8522 *
8523 * We have two devices reporting events:
8524 * - Device A reports ACTION_DOWN, which lands in the left window
8525 * - Device B reports ACTION_DOWN, which lands in the spy window.
8526 * - Now, device B reports ACTION_MOVE events which move to the right window.
8527 *
8528 * The right window should not receive any events because the spy window is not a foreground window,
8529 * and also it does not support slippery touches.
8530 */
8531TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
8532 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8533 sp<FakeWindowHandle> leftWindow =
8534 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008535 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008536 leftWindow->setFrame(Rect(0, 0, 100, 100));
8537 leftWindow->setSlippery(true);
8538
8539 sp<FakeWindowHandle> rightWindow =
8540 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008541 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008542 rightWindow->setFrame(Rect(100, 0, 200, 100));
8543
8544 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008545 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8546 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008547 spyWindow->setFrame(Rect(200, 0, 300, 100));
8548 spyWindow->setSpy(true);
8549 spyWindow->setTrustedOverlay(true);
8550
8551 mDispatcher->onWindowInfosChanged(
8552 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
8553
8554 const DeviceId deviceA = 9;
8555 const DeviceId deviceB = 3;
8556
8557 // Tap on left window with device A
8558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8559 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8560 .deviceId(deviceA)
8561 .build());
8562 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8563
8564 // Tap on spy window with device B
8565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8566 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8567 .deviceId(deviceB)
8568 .build());
8569 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8570
8571 // Move to right window with device B. Touches should not slip to the right window, because spy
8572 // window is not a foreground window, and it does not have FLAG_SLIPPERY
8573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8574 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8575 .deviceId(deviceB)
8576 .build());
8577 leftWindow->assertNoEvents();
8578 rightWindow->assertNoEvents();
8579 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8580}
8581
8582/**
8583 * Three windows arranged horizontally and without any overlap.
8584 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
8585 *
8586 * We have two devices reporting events:
8587 * - Device A reports ACTION_DOWN which lands in the left window
8588 * - Device B reports ACTION_DOWN which lands in the right window
8589 * - Device B reports ACTION_MOVE that shifts to the middle window.
8590 * This should cause touches for Device B to slip from the right window to the middle window.
8591 * The right window should receive ACTION_CANCEL for device B and the
8592 * middle window should receive down event for Device B.
8593 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
8594 */
8595TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07008596 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08008597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8598 sp<FakeWindowHandle> leftWindow =
8599 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008600 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008601 leftWindow->setFrame(Rect(0, 0, 100, 100));
8602 leftWindow->setSlippery(true);
8603
8604 sp<FakeWindowHandle> middleWindow =
8605 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008606 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008607 middleWindow->setFrame(Rect(100, 0, 200, 100));
8608
8609 sp<FakeWindowHandle> rightWindow =
8610 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008611 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008612 rightWindow->setFrame(Rect(200, 0, 300, 100));
8613 rightWindow->setSlippery(true);
8614
8615 mDispatcher->onWindowInfosChanged(
8616 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
8617 {},
8618 0,
8619 0});
8620
8621 const DeviceId deviceA = 9;
8622 const DeviceId deviceB = 3;
8623
8624 // Tap on left window with device A
8625 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8626 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8627 .deviceId(deviceA)
8628 .build());
8629 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8630
8631 // Tap on right window with device B
8632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8633 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8634 .deviceId(deviceB)
8635 .build());
8636 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8637
8638 // Move to middle window with device B. Touches should slip to middle window, because right
8639 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8641 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8642 .deviceId(deviceB)
8643 .build());
8644 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8645 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8646
8647 // Move to middle window with device A. Touches should slip to middle window, because left
8648 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8650 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8651 .deviceId(deviceA)
8652 .build());
8653 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8654 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8655
8656 // Ensure that middle window can receive the remaining move events.
8657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8658 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8659 .deviceId(deviceB)
8660 .build());
8661 leftWindow->assertNoEvents();
8662 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8663 rightWindow->assertNoEvents();
8664}
8665
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008666TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008667 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8669
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008670 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8671 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008672 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008673 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008674
8675 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008676 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8677 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008678 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008679 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008680 rightSpy->setSpy(true);
8681 rightSpy->setTrustedOverlay(true);
8682
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008683 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8684 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008685 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008686 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008687
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008688 mDispatcher->onWindowInfosChanged(
8689 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008690
8691 // Touch in the left window
8692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8693 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8694 .build());
8695 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8696 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008697 ASSERT_NO_FATAL_FAILURE(
8698 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008699
8700 // Touch another finger over the right windows
8701 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8702 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8703 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8704 .build());
8705 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8706 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8707 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8708 mDispatcher->waitForIdle();
8709 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008710 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8711 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008712
8713 // Release finger over left window. The UP actions are not treated as device interaction.
8714 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8715 // is part of the UP action, we do not treat this as device interaction.
8716 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8717 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8718 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8719 .build());
8720 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8721 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8722 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8723 mDispatcher->waitForIdle();
8724 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8725
8726 // Move remaining finger
8727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8728 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8729 .build());
8730 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8731 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8732 mDispatcher->waitForIdle();
8733 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008734 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008735
8736 // Release all fingers
8737 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8738 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8739 .build());
8740 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8741 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8742 mDispatcher->waitForIdle();
8743 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8744}
8745
8746TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8747 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8748
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8750 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008751 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008752 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008753
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008754 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008755 setFocusedWindow(window);
8756 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8757
8758 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008759 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008760 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008761 ASSERT_NO_FATAL_FAILURE(
8762 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008763
8764 // The UP actions are not treated as device interaction.
8765 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008766 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008767 mDispatcher->waitForIdle();
8768 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8769}
8770
Prabir Pradhan5893d362023-11-17 04:30:40 +00008771TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8772 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8773
8774 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008775 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008776 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008777 sp<FakeWindowHandle> right =
8778 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8779 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008780 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008781 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8782 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008783 spy->setFrame(Rect(0, 0, 200, 100));
8784 spy->setTrustedOverlay(true);
8785 spy->setSpy(true);
8786
8787 mDispatcher->onWindowInfosChanged(
8788 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8789
8790 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008791 NotifyMotionArgs notifyArgs =
8792 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8793 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008794 mDispatcher->notifyMotion(notifyArgs);
8795
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008796 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008797 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8798 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008799 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008800 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8801 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008802 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008803 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8804
8805 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008806 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8807 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008808 mDispatcher->notifyMotion(notifyArgs);
8809
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008810 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008811 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8812 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008813 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008814 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8815 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008816 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008817 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8818
8819 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8820}
8821
Linnan Liccf6ce32024-04-11 20:32:13 +08008822/**
8823 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8824 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8825 * the previous window should receive this event and not be dropped.
8826 */
8827TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07008828 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Linnan Liccf6ce32024-04-11 20:32:13 +08008829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8831 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008832 window->setFrame(Rect(0, 0, 100, 100));
8833 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8834
8835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8836 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8837 .build());
8838
8839 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8840
8841 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8842 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8843 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8844 .build());
8845
8846 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8847}
8848
8849/**
8850 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8851 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8852 * previous window should receive deviceB's event and it should be dropped.
8853 */
8854TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008856 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8857 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008858 window->setFrame(Rect(0, 0, 100, 100));
8859 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8860
8861 const DeviceId deviceA = 9;
8862 const DeviceId deviceB = 3;
8863
8864 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8865 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8866 .deviceId(deviceA)
8867 .build());
8868 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8869
8870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8871 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8872 .deviceId(deviceB)
8873 .build());
8874 window->assertNoEvents();
8875}
8876
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008877class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8878protected:
8879 std::shared_ptr<FakeApplicationHandle> mApp;
8880 sp<FakeWindowHandle> mWindow;
8881
8882 virtual void SetUp() override {
8883 InputDispatcherTest::SetUp();
8884
8885 mApp = std::make_shared<FakeApplicationHandle>();
8886
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008887 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8888 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008889 mWindow->setFrame(Rect(0, 0, 100, 100));
8890
8891 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8892 setFocusedWindow(mWindow);
8893 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8894 }
8895
8896 void setFallback(int32_t keycode) {
8897 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8898 return KeyEventBuilder(event).keyCode(keycode).build();
8899 });
8900 }
8901
8902 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008903 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8904 ASSERT_NE(nullptr, event);
8905 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008906 }
8907};
8908
8909TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8910 mDispatcher->notifyKey(
8911 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8912 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8913 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8914}
8915
8916TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8917 mDispatcher->notifyKey(
8918 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8919 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8920 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8921}
8922
8923TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8924 mDispatcher->notifyKey(
8925 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8926
8927 // Do not handle this key event.
8928 consumeKey(/*handled=*/false,
8929 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8930 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8931
8932 // Since the policy did not request any fallback to be generated, ensure there are no events.
8933 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8934}
8935
8936TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8937 setFallback(AKEYCODE_B);
8938 mDispatcher->notifyKey(
8939 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8940
8941 // Do not handle this key event.
8942 consumeKey(/*handled=*/false,
8943 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8944
8945 // Since the key was not handled, ensure the fallback event was dispatched instead.
8946 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8947 consumeKey(/*handled=*/true,
8948 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8949 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8950
8951 // Release the original key, and ensure the fallback key is also released.
8952 mDispatcher->notifyKey(
8953 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8954 consumeKey(/*handled=*/false,
8955 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8956 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8957 consumeKey(/*handled=*/true,
8958 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8959 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8960
8961 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8962 mWindow->assertNoEvents();
8963}
8964
8965TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8966 setFallback(AKEYCODE_B);
8967 mDispatcher->notifyKey(
8968 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8969
8970 // Do not handle this key event, but handle the fallback.
8971 consumeKey(/*handled=*/false,
8972 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8973 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8974 consumeKey(/*handled=*/true,
8975 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8976 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8977
8978 // Release the original key, and ensure the fallback key is also released.
8979 mDispatcher->notifyKey(
8980 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8981 // But this time, the app handles the original key.
8982 consumeKey(/*handled=*/true,
8983 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8984 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8985 // Ensure the fallback key is canceled.
8986 consumeKey(/*handled=*/true,
8987 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8988 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8989
8990 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8991 mWindow->assertNoEvents();
8992}
8993
8994TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8995 setFallback(AKEYCODE_B);
8996 mDispatcher->notifyKey(
8997 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8998
8999 // Do not handle this key event.
9000 consumeKey(/*handled=*/false,
9001 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9002 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9003 // App does not handle the fallback either, so ensure another fallback is not generated.
9004 setFallback(AKEYCODE_C);
9005 consumeKey(/*handled=*/false,
9006 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9007 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9008
9009 // Release the original key, and ensure the fallback key is also released.
9010 setFallback(AKEYCODE_B);
9011 mDispatcher->notifyKey(
9012 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9013 consumeKey(/*handled=*/false,
9014 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9015 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9016 consumeKey(/*handled=*/false,
9017 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9018 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9019
9020 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9021 mWindow->assertNoEvents();
9022}
9023
9024TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
9025 setFallback(AKEYCODE_B);
9026 mDispatcher->notifyKey(
9027 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9028
9029 // Do not handle this key event, so fallback is generated.
9030 consumeKey(/*handled=*/false,
9031 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9032 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9033 consumeKey(/*handled=*/true,
9034 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9035 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9036
9037 // Release the original key, but assume the policy is misbehaving and it
9038 // generates an inconsistent fallback to the one from the DOWN event.
9039 setFallback(AKEYCODE_C);
9040 mDispatcher->notifyKey(
9041 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9042 consumeKey(/*handled=*/false,
9043 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9044 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9045 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
9046 consumeKey(/*handled=*/true,
9047 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9048 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9049
9050 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9051 mWindow->assertNoEvents();
9052}
9053
9054TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
9055 setFallback(AKEYCODE_B);
9056 mDispatcher->notifyKey(
9057 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9058
9059 // Do not handle this key event, so fallback is generated.
9060 consumeKey(/*handled=*/false,
9061 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9062 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9063 consumeKey(/*handled=*/true,
9064 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9065 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9066
9067 // The original key is canceled.
9068 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
9069 .keyCode(AKEYCODE_A)
9070 .addFlag(AKEY_EVENT_FLAG_CANCELED)
9071 .build());
9072 consumeKey(/*handled=*/false,
9073 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9074 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9075 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9076 // Ensure the fallback key is also canceled due to the original key being canceled.
9077 consumeKey(/*handled=*/true,
9078 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9079 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9080
9081 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
9082 mWindow->assertNoEvents();
9083}
9084
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00009085TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00009086 setFallback(AKEYCODE_B);
9087 mDispatcher->notifyKey(
9088 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9089
9090 // Do not handle this key event.
9091 consumeKey(/*handled=*/false,
9092 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9093 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9094 consumeKey(/*handled=*/true,
9095 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9096 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9097
9098 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9099 // When the unhandled key is reported to the policy next, remove the input channel.
9100 mDispatcher->removeInputChannel(mWindow->getToken());
9101 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9102 });
9103 // Release the original key, and let the app now handle the previously unhandled key.
9104 // This should result in the previously generated fallback key to be cancelled.
9105 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
9106 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
9107 // without holding the lock, because it need to synchronously fetch the fallback key. While in
9108 // the policy call, we will now remove the input channel. Once the policy call returns, the
9109 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
9110 // not cause any crashes.
9111 mDispatcher->notifyKey(
9112 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9113 consumeKey(/*handled=*/true,
9114 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9115 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9116}
9117
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00009118TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
9119 setFallback(AKEYCODE_B);
9120 mDispatcher->notifyKey(
9121 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9122
9123 // Do not handle this key event.
9124 consumeKey(/*handled=*/false,
9125 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9126 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9127 consumeKey(/*handled=*/true,
9128 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9129 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9130
9131 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9132 // When the unhandled key is reported to the policy next, remove the window.
9133 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9134 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9135 });
9136 // Release the original key, which the app will not handle. When this unhandled key is reported
9137 // to the policy, the window will be removed.
9138 mDispatcher->notifyKey(
9139 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9140 consumeKey(/*handled=*/false,
9141 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9142 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9143
9144 // Since the window was removed, it loses focus, and the channel state will be reset.
9145 consumeKey(/*handled=*/true,
9146 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9147 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9148 mWindow->consumeFocusEvent(false);
9149 mWindow->assertNoEvents();
9150}
9151
9152TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
9153 setFallback(AKEYCODE_B);
9154 mDispatcher->notifyKey(
9155 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9156
9157 // Do not handle this key event.
9158 consumeKey(/*handled=*/false,
9159 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9160 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9161 const auto [seq, event] = mWindow->receiveEvent();
9162 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
9163 ASSERT_EQ(event->getType(), InputEventType::KEY);
9164 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
9165 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9166 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9167
9168 // Remove the window now, which should generate a cancellations and make the window lose focus.
9169 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9170 consumeKey(/*handled=*/true,
9171 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9172 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9173 consumeKey(/*handled=*/true,
9174 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9175 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9176 mWindow->consumeFocusEvent(false);
9177
9178 // Finish the event by reporting it as handled.
9179 mWindow->finishEvent(*seq);
9180 mWindow->assertNoEvents();
9181}
9182
Garfield Tan1c7bc862020-01-28 13:24:04 -08009183class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
9184protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08009185 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
9186 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009187 static constexpr bool KEY_REPEAT_ENABLED = true;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009188
Chris Yea209fde2020-07-22 13:54:51 -07009189 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009190 sp<FakeWindowHandle> mWindow;
9191
9192 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00009193 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08009194
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009195 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9196 KEY_REPEAT_ENABLED);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009197 setUpWindow();
9198 }
9199
9200 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07009201 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009202 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
9203 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009204
Vishnu Nair47074b82020-08-14 11:54:47 -07009205 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009206 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009207 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009208 mWindow->consumeFocusEvent(true);
9209 }
9210
Chris Ye2ad95392020-09-01 13:44:44 -07009211 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009212 NotifyKeyArgs keyArgs =
9213 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07009214 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009215 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00009216 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009217
9218 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009219 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009220 }
9221
9222 void expectKeyRepeatOnce(int32_t repeatCount) {
9223 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009224 mWindow->consumeKeyEvent(
9225 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08009226 }
9227
Chris Ye2ad95392020-09-01 13:44:44 -07009228 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009229 NotifyKeyArgs keyArgs =
9230 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07009231 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009232 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00009233 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009234
9235 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009236 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00009237 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009238 }
Hu Guofe3c8f12023-09-22 17:20:15 +08009239
9240 void injectKeyRepeat(int32_t repeatCount) {
9241 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009242 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
9243 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08009244 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9245 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08009246};
9247
9248TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00009249 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009250 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9251 expectKeyRepeatOnce(repeatCount);
9252 }
9253}
9254
9255TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00009256 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009257 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9258 expectKeyRepeatOnce(repeatCount);
9259 }
Harry Cutts33476232023-01-30 19:57:29 +00009260 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009261 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08009262 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9263 expectKeyRepeatOnce(repeatCount);
9264 }
9265}
9266
9267TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009268 sendAndConsumeKeyDown(/*deviceId=*/1);
9269 expectKeyRepeatOnce(/*repeatCount=*/1);
9270 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009271 mWindow->assertNoEvents();
9272}
9273
9274TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009275 sendAndConsumeKeyDown(/*deviceId=*/1);
9276 expectKeyRepeatOnce(/*repeatCount=*/1);
9277 sendAndConsumeKeyDown(/*deviceId=*/2);
9278 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009279 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00009280 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009281 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00009282 expectKeyRepeatOnce(/*repeatCount=*/2);
9283 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07009284 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00009285 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009286 mWindow->assertNoEvents();
9287}
9288
9289TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009290 sendAndConsumeKeyDown(/*deviceId=*/1);
9291 expectKeyRepeatOnce(/*repeatCount=*/1);
9292 sendAndConsumeKeyDown(/*deviceId=*/2);
9293 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009294 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00009295 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009296 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08009297 mWindow->assertNoEvents();
9298}
9299
liushenxiang42232912021-05-21 20:24:09 +08009300TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
9301 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00009302 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009303 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009304 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08009305 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
9306 mWindow->assertNoEvents();
9307}
9308
Garfield Tan1c7bc862020-01-28 13:24:04 -08009309TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00009310 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00009311 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009312 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009313 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9314 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009315 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009316 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08009317 }
9318}
9319
9320TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00009321 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00009322 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009323
9324 std::unordered_set<int32_t> idSet;
9325 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009326 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9327 ASSERT_NE(nullptr, repeatEvent);
9328 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08009329 EXPECT_EQ(idSet.end(), idSet.find(id));
9330 idSet.insert(id);
9331 }
9332}
9333
Hu Guofe3c8f12023-09-22 17:20:15 +08009334TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
9335 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009336 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08009337 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
9338 expectKeyRepeatOnce(repeatCount);
9339 }
9340 injectKeyRepeat(1);
9341 // Expect repeatCount to be 3 instead of 1
9342 expectKeyRepeatOnce(3);
9343}
9344
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009345TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_NoRepeatWhenKeyRepeatDisabled) {
9346 SCOPED_FLAG_OVERRIDE(keyboard_repeat_keys, true);
9347 static constexpr std::chrono::milliseconds KEY_NO_REPEAT_ASSERTION_TIMEOUT = 100ms;
9348
9349 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9350 /*repeatKeyEnabled=*/false);
9351 sendAndConsumeKeyDown(/*deviceId=*/1);
9352
9353 ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_TIMEOUT)
9354 << "Ensure the check for no key repeats extends beyond the repeat timeout duration.";
9355 ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_DELAY)
9356 << "Ensure the check for no key repeats extends beyond the repeat delay duration.";
9357
9358 // No events should be returned if key repeat is turned off.
9359 // Wait for KEY_NO_REPEAT_ASSERTION_TIMEOUT to return no events to ensure key repeat disabled.
9360 mWindow->assertNoEvents(KEY_NO_REPEAT_ASSERTION_TIMEOUT);
9361}
9362
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009363/* Test InputDispatcher for MultiDisplay */
9364class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
9365public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009366 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009367 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08009368
Chris Yea209fde2020-07-22 13:54:51 -07009369 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009370 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
9371 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009372
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009373 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009374 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07009375 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009376 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
9377
Vishnu Nair958da932020-08-21 17:12:37 -07009378 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009379 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08009380
Chris Yea209fde2020-07-22 13:54:51 -07009381 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009382 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009383 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009384 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009385 // Set focus display to second one.
9386 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00009387 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
9388
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009389 // Set focus window for second display.
9390 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07009391 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009392 mDispatcher->onWindowInfosChanged(
9393 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009394 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009395 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009396 }
9397
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009398 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009399 InputDispatcherTest::TearDown();
9400
Chris Yea209fde2020-07-22 13:54:51 -07009401 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009402 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07009403 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009404 windowInSecondary.clear();
9405 }
9406
9407protected:
Chris Yea209fde2020-07-22 13:54:51 -07009408 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009409 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07009410 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009411 sp<FakeWindowHandle> windowInSecondary;
9412};
9413
9414TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
9415 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009416 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009417 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9418 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009419 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009420 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08009421 windowInSecondary->assertNoEvents();
9422
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009423 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009425 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009427 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009428 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009429}
9430
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009431TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08009432 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009434 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009435 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009436 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08009437 windowInSecondary->assertNoEvents();
9438
9439 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009441 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009442 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009443 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009444
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009445 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009446 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08009447
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009448 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009449 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08009450
9451 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009452 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08009453 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009454 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08009455 windowInSecondary->assertNoEvents();
9456}
9457
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009458// Test per-display input monitors for motion event.
9459TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08009460 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009461 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009462 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009463 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009464
9465 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009467 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9468 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009470 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9471 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009472 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009473 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009474
9475 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009477 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009479 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009480 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009481 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08009482 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009483
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009484 // Lift up the touch from the second display
9485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009486 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9488 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
9489 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
9490
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009491 // Test inject a non-pointer motion event.
9492 // If specific a display, it will dispatch to the focused window of particular display,
9493 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009495 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
9496 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009497 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009498 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009499 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009500 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
9501 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009502}
9503
9504// Test per-display input monitors for key event.
9505TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009506 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08009507 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009508 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009509 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009510 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009511
9512 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009514 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009515 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009516 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009517 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9518 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009519}
9520
Vishnu Nair958da932020-08-21 17:12:37 -07009521TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
9522 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009523 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
9524 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009525 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009526 mDispatcher->onWindowInfosChanged(
9527 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
9528 *windowInSecondary->getInfo()},
9529 {},
9530 0,
9531 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009532 setFocusedWindow(secondWindowInPrimary);
9533 windowInPrimary->consumeFocusEvent(false);
9534 secondWindowInPrimary->consumeFocusEvent(true);
9535
9536 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009537 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009538 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009539 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009540 windowInPrimary->assertNoEvents();
9541 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009542 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009543}
9544
Arthur Hungdfd528e2021-12-08 13:23:04 +00009545TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
9546 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009547 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009548 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009549 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009550
9551 // Test touch down on primary display.
9552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009553 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9554 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009556 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9557 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009558
9559 // Test touch down on second display.
9560 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009561 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9563 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9564 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9565
9566 // Trigger cancel touch.
9567 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009568 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9569 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009570 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
9571 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
9572
9573 // Test inject a move motion event, no window/monitor should receive the event.
9574 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009575 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009576 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009577 << "Inject motion event should return InputEventInjectionResult::FAILED";
9578 windowInPrimary->assertNoEvents();
9579 monitorInPrimary.assertNoEvents();
9580
9581 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009582 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00009583 SECOND_DISPLAY_ID, {110, 200}))
9584 << "Inject motion event should return InputEventInjectionResult::FAILED";
9585 windowInSecondary->assertNoEvents();
9586 monitorInSecondary.assertNoEvents();
9587}
9588
Hu Guocb134f12023-12-23 13:42:44 +00009589/**
9590 * Send a key to the primary display and to the secondary display.
9591 * Then cause the key on the primary display to be canceled by sending in a stale key.
9592 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
9593 * does not get canceled.
9594 */
9595TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
9596 // Send a key down on primary display
9597 mDispatcher->notifyKey(
9598 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009599 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009600 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9601 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009602 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
9603 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009604 windowInSecondary->assertNoEvents();
9605
9606 // Send a key down on second display
9607 mDispatcher->notifyKey(
9608 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9609 .displayId(SECOND_DISPLAY_ID)
9610 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9611 .build());
9612 windowInSecondary->consumeKeyEvent(
9613 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9614 windowInPrimary->assertNoEvents();
9615
9616 // Send a valid key up event on primary display that will be dropped because it is stale
9617 NotifyKeyArgs staleKeyUp =
9618 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009619 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009620 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9621 .build();
9622 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9623 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9624 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9625 mDispatcher->notifyKey(staleKeyUp);
9626
9627 // Only the key gesture corresponding to the dropped event should receive the cancel event.
9628 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
9629 // receive any events.
9630 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009631 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00009632 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9633 windowInSecondary->assertNoEvents();
9634}
9635
9636/**
9637 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
9638 */
9639TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
9640 // Send touch down on primary display.
9641 mDispatcher->notifyMotion(
9642 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9643 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009644 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009645 .build());
9646 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009647 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009648 windowInSecondary->assertNoEvents();
9649
9650 // Send touch down on second display.
9651 mDispatcher->notifyMotion(
9652 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9653 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9654 .displayId(SECOND_DISPLAY_ID)
9655 .build());
9656 windowInPrimary->assertNoEvents();
9657 windowInSecondary->consumeMotionEvent(
9658 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9659
9660 // inject a valid MotionEvent on primary display that will be stale when it arrives.
9661 NotifyMotionArgs staleMotionUp =
9662 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009663 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009664 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9665 .build();
9666 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9667 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9668 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9669 mDispatcher->notifyMotion(staleMotionUp);
9670
9671 // For stale motion events, we let the gesture to complete. This behaviour is different from key
9672 // events, where we would cancel the current keys instead.
9673 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9674 windowInSecondary->assertNoEvents();
9675}
9676
Jackal Guof9696682018-10-05 12:23:23 +08009677class InputFilterTest : public InputDispatcherTest {
9678protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08009679 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009680 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08009681 NotifyMotionArgs motionArgs;
9682
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009683 motionArgs =
9684 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009685 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009686 motionArgs =
9687 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009688 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009689 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009690 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009691 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009692 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08009693 } else {
9694 mFakePolicy->assertFilterInputEventWasNotCalled();
9695 }
9696 }
9697
9698 void testNotifyKey(bool expectToBeFiltered) {
9699 NotifyKeyArgs keyArgs;
9700
9701 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009702 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009703 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009704 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009705 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009706
9707 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009708 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009709 } else {
9710 mFakePolicy->assertFilterInputEventWasNotCalled();
9711 }
9712 }
9713};
9714
9715// Test InputFilter for MotionEvent
9716TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9717 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009718 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009719 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009720
9721 // Enable InputFilter
9722 mDispatcher->setInputFilterEnabled(true);
9723 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009724 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009725 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009726
9727 // Disable InputFilter
9728 mDispatcher->setInputFilterEnabled(false);
9729 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009730 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009731 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009732}
9733
9734// Test InputFilter for KeyEvent
9735TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9736 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009737 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009738
9739 // Enable InputFilter
9740 mDispatcher->setInputFilterEnabled(true);
9741 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009742 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009743
9744 // Disable InputFilter
9745 mDispatcher->setInputFilterEnabled(false);
9746 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009747 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009748}
9749
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009750// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9751// logical display coordinate space.
9752TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9753 ui::Transform firstDisplayTransform;
9754 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9755 ui::Transform secondDisplayTransform;
9756 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9757
9758 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009759 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009760 displayInfos[0].transform = firstDisplayTransform;
9761 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9762 displayInfos[1].transform = secondDisplayTransform;
9763
Patrick Williamsd828f302023-04-28 17:52:08 -05009764 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009765
9766 // Enable InputFilter
9767 mDispatcher->setInputFilterEnabled(true);
9768
9769 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009770 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9771 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009772 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009773}
9774
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009775class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9776protected:
9777 virtual void SetUp() override {
9778 InputDispatcherTest::SetUp();
9779
9780 /**
9781 * We don't need to enable input filter to test the injected event policy, but we enabled it
9782 * here to make the tests more realistic, since this policy only matters when inputfilter is
9783 * on.
9784 */
9785 mDispatcher->setInputFilterEnabled(true);
9786
9787 std::shared_ptr<InputApplicationHandle> application =
9788 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009789 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009790 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009791
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009792 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009793 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009794 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009795 setFocusedWindow(mWindow);
9796 mWindow->consumeFocusEvent(true);
9797 }
9798
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009799 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9800 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009801 KeyEvent event;
9802
9803 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9804 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009805 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9806 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009807 const int32_t additionalPolicyFlags =
9808 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009810 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009811 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009812 policyFlags | additionalPolicyFlags));
9813
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009814 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009815 }
9816
9817 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9818 int32_t flags) {
9819 MotionEvent event;
9820 PointerProperties pointerProperties[1];
9821 PointerCoords pointerCoords[1];
9822 pointerProperties[0].clear();
9823 pointerProperties[0].id = 0;
9824 pointerCoords[0].clear();
9825 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9826 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9827
9828 ui::Transform identityTransform;
9829 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9830 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9831 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9832 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9833 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009834 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009835 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009836 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009837
9838 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009840 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009841 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009842 policyFlags | additionalPolicyFlags));
9843
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009844 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009845 }
9846
9847private:
9848 sp<FakeWindowHandle> mWindow;
9849};
9850
9851TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009852 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9853 // filter. Without it, the event will no different from a regularly injected event, and the
9854 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009855 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9856 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009857}
9858
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009859TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009860 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009861 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009862 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9863}
9864
9865TEST_F(InputFilterInjectionPolicyTest,
9866 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9867 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009868 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009869 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009870}
9871
9872TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009873 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9874 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009875}
9876
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009877class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9878protected:
9879 virtual void SetUp() override {
9880 InputDispatcherTest::SetUp();
9881
9882 std::shared_ptr<FakeApplicationHandle> application =
9883 std::make_shared<FakeApplicationHandle>();
9884 application->setDispatchingTimeout(100ms);
9885 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009886 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009887 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009888 mWindow->setDispatchingTimeout(100ms);
9889 mWindow->setFocusable(true);
9890
9891 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009892 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009893
9894 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9895 setFocusedWindow(mWindow);
9896 mWindow->consumeFocusEvent(true);
9897 }
9898
Linnan Li13bf76a2024-05-05 19:18:02 +08009899 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009900 nsecs_t eventTime) {
9901 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9902 .displayId(displayId)
9903 .eventTime(eventTime)
9904 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9905 .build());
9906 mWindow->consumeMotionEvent(WithMotionAction(action));
9907 }
9908
9909private:
9910 sp<FakeWindowHandle> mWindow;
9911};
9912
9913TEST_F_WITH_FLAGS(
9914 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9915 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9916 rate_limit_user_activity_poke_in_dispatcher))) {
9917 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9918
9919 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009920 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009921 milliseconds_to_nanoseconds(50));
9922 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009923 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9924 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009925
9926 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009927 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009928 milliseconds_to_nanoseconds(130));
9929 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009930 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9931 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009932
9933 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009934 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9935 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009936 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009937 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9938 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009939
9940 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009941 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009942 milliseconds_to_nanoseconds(140));
9943 mFakePolicy->assertUserActivityNotPoked();
9944
9945 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009946 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9947 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009948 mFakePolicy->assertUserActivityNotPoked();
9949
9950 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9951 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009952 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009953 milliseconds_to_nanoseconds(160));
9954 mFakePolicy->assertUserActivityNotPoked();
9955
9956 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009957 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9958 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009959 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009960 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9961 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009962
9963 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009964 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009965 milliseconds_to_nanoseconds(300));
9966 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009967 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9968 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009969
9970 // Assert that there's no more user activity poke event.
9971 mFakePolicy->assertUserActivityNotPoked();
9972}
9973
9974TEST_F_WITH_FLAGS(
9975 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9976 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9977 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009978 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009979 milliseconds_to_nanoseconds(200));
9980 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009981 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9982 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009983
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009984 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009985 milliseconds_to_nanoseconds(280));
9986 mFakePolicy->assertUserActivityNotPoked();
9987
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009988 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009989 milliseconds_to_nanoseconds(340));
9990 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009991 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9992 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009993}
9994
9995TEST_F_WITH_FLAGS(
9996 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9997 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9998 rate_limit_user_activity_poke_in_dispatcher))) {
9999 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
10000
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010001 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
10002 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -080010003 mFakePolicy->assertUserActivityPoked();
10004
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010005 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
10006 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -080010007 mFakePolicy->assertUserActivityPoked();
10008}
10009
chaviwfd6d3512019-03-25 13:23:49 -070010010class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -070010011 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -070010012 InputDispatcherTest::SetUp();
10013
Chris Yea209fde2020-07-22 13:54:51 -070010014 std::shared_ptr<FakeApplicationHandle> application =
10015 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010016 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
10017 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -070010018 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -070010019
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010020 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
10021 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -080010022 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -070010023
10024 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010025 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -070010026 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -070010027
10028 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010029 mDispatcher->onWindowInfosChanged(
10030 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010031 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +010010032 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -070010033 }
10034
Prabir Pradhan3608aad2019-10-02 17:08:26 -070010035 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -070010036 InputDispatcherTest::TearDown();
10037
10038 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -080010039 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -070010040 }
10041
10042protected:
10043 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -080010044 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -070010045 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -070010046};
10047
10048// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
10049// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
10050// the onPointerDownOutsideFocus callback.
10051TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010052 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010053 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10054 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010055 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010056 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010057
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010058 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -070010059 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
10060}
10061
10062// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
10063// DOWN on the window that doesn't have focus. Ensure no window received the
10064// onPointerDownOutsideFocus callback.
10065TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010067 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010068 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010069 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010070 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010071
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010072 ASSERT_TRUE(mDispatcher->waitForIdle());
10073 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010074}
10075
10076// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
10077// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
10078TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -080010079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010080 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010081 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010082 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -070010083
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010084 ASSERT_TRUE(mDispatcher->waitForIdle());
10085 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010086}
10087
10088// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
10089// DOWN on the window that already has focus. Ensure no window received the
10090// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100010091TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010092 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010093 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10094 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010095 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010096 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010097
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010098 ASSERT_TRUE(mDispatcher->waitForIdle());
10099 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010100}
10101
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010102// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
10103// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
10104TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
10105 const MotionEvent event =
10106 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
10107 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010108 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010109 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
10110 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010112 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010113 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
10114 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010115
10116 ASSERT_TRUE(mDispatcher->waitForIdle());
10117 mFakePolicy->assertOnPointerDownWasNotCalled();
10118 // Ensure that the unfocused window did not receive any FOCUS events.
10119 mUnfocusedWindow->assertNoEvents();
10120}
10121
chaviwaf87b3e2019-10-01 16:59:28 -070010122// These tests ensures we can send touch events to a single client when there are multiple input
10123// windows that point to the same client token.
10124class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
10125 virtual void SetUp() override {
10126 InputDispatcherTest::SetUp();
10127
Chris Yea209fde2020-07-22 13:54:51 -070010128 std::shared_ptr<FakeApplicationHandle> application =
10129 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010130 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010131 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -070010132 mWindow1->setFrame(Rect(0, 0, 100, 100));
10133
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010134 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -070010135 mWindow2->setFrame(Rect(100, 100, 200, 200));
10136
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010137 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -070010138 }
10139
10140protected:
10141 sp<FakeWindowHandle> mWindow1;
10142 sp<FakeWindowHandle> mWindow2;
10143
10144 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -050010145 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -070010146 vec2 vals = windowInfo->transform.transform(point.x, point.y);
10147 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -070010148 }
10149
10150 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
10151 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +010010152 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010153 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010154 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010155 ASSERT_NE(nullptr, motionEvent);
10156 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -070010157
10158 for (size_t i = 0; i < points.size(); i++) {
10159 float expectedX = points[i].x;
10160 float expectedY = points[i].y;
10161
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010162 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -070010163 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010164 << ", got " << motionEvent->getX(i);
10165 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -070010166 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010167 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -070010168 }
10169 }
chaviw9eaa22c2020-07-01 16:21:27 -070010170
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010171 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
10172 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -070010173 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010174 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010175 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -070010176
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010177 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010178 }
chaviwaf87b3e2019-10-01 16:59:28 -070010179};
10180
10181TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
10182 // Touch Window 1
10183 PointF touchedPoint = {10, 10};
10184 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010185 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010186
10187 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010188 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010189
10190 // Touch Window 2
10191 touchedPoint = {150, 150};
10192 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010193 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010194}
10195
chaviw9eaa22c2020-07-01 16:21:27 -070010196TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
10197 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -070010198 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010199 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -070010200
10201 // Touch Window 1
10202 PointF touchedPoint = {10, 10};
10203 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010204 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010205 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010206 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010207
10208 // Touch Window 2
10209 touchedPoint = {150, 150};
10210 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010211 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10212 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010213
chaviw9eaa22c2020-07-01 16:21:27 -070010214 // Update the transform so rotation is set
10215 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010216 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010217 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010218 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010219}
10220
chaviw9eaa22c2020-07-01 16:21:27 -070010221TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010222 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010223 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010224
10225 // Touch Window 1
10226 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10227 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010228 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010229
10230 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010231 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
10232 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
10233 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -070010234 touchedPoints.push_back(PointF{150, 150});
10235 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010236 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010237
chaviw9eaa22c2020-07-01 16:21:27 -070010238 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010239 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010240 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010241
chaviw9eaa22c2020-07-01 16:21:27 -070010242 // Update the transform so rotation is set for Window 2
10243 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010244 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010245 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010246 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010247}
10248
chaviw9eaa22c2020-07-01 16:21:27 -070010249TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010250 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010251 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010252
10253 // Touch Window 1
10254 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10255 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010256 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010257
10258 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -070010259 touchedPoints.push_back(PointF{150, 150});
10260 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010261
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010262 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010263
10264 // Move both windows
10265 touchedPoints = {{20, 20}, {175, 175}};
10266 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10267 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10268
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010269 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010270
chaviw9eaa22c2020-07-01 16:21:27 -070010271 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010272 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010273 expectedPoints.pop_back();
10274
10275 // Touch Window 2
10276 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010277 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010278 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010279 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010280
10281 // Move both windows
10282 touchedPoints = {{20, 20}, {175, 175}};
10283 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10284 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10285
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010286 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010287}
10288
10289TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
10290 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010291 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010292
10293 // Touch Window 1
10294 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10295 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010296 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010297
10298 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -070010299 touchedPoints.push_back(PointF{150, 150});
10300 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010301
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010302 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010303
10304 // Move both windows
10305 touchedPoints = {{20, 20}, {175, 175}};
10306 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10307 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10308
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010309 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010310}
10311
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010312/**
10313 * When one of the windows is slippery, the touch should not slip into the other window with the
10314 * same input channel.
10315 */
10316TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
10317 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010318 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010319
10320 // Touch down in window 1
10321 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010322 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010323 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
10324
10325 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
10326 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
10327 // getting generated.
10328 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010329 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010330
10331 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
10332}
10333
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010334/**
10335 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
10336 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
10337 * that the pointer is hovering over may have a different transform.
10338 */
10339TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010340 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010341
10342 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010343 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
10344 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10345 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010346 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
10347 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010348 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010349 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10350 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10351 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010352 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010353 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010354 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
10355}
10356
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010357class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
10358 virtual void SetUp() override {
10359 InputDispatcherTest::SetUp();
10360
Chris Yea209fde2020-07-22 13:54:51 -070010361 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010362 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010363 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010364 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010365 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010366 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -070010367 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010368
10369 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010370 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010371
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010372 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010373 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010374 mWindow->consumeFocusEvent(true);
10375 }
10376
10377 virtual void TearDown() override {
10378 InputDispatcherTest::TearDown();
10379 mWindow.clear();
10380 }
10381
10382protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010383 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -070010384 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010385 sp<FakeWindowHandle> mWindow;
10386 static constexpr PointF WINDOW_LOCATION = {20, 20};
10387
10388 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010389 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
10390 .x(WINDOW_LOCATION.x)
10391 .y(WINDOW_LOCATION.y);
10392 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10393 .pointer(touchingPointer)
10394 .build());
10395 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10396 .pointer(touchingPointer)
10397 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010398 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010399
10400 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010401 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
10402 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010403 spy->setTrustedOverlay(true);
10404 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010405 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010406 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010407 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010408 return spy;
10409 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010410};
10411
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010412// Send a tap and respond, which should not cause an ANR.
10413TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
10414 tapOnWindow();
10415 mWindow->consumeMotionDown();
10416 mWindow->consumeMotionUp();
10417 ASSERT_TRUE(mDispatcher->waitForIdle());
10418 mFakePolicy->assertNotifyAnrWasNotCalled();
10419}
10420
10421// Send a regular key and respond, which should not cause an ANR.
10422TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010424 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010425 ASSERT_TRUE(mDispatcher->waitForIdle());
10426 mFakePolicy->assertNotifyAnrWasNotCalled();
10427}
10428
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010429TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
10430 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010431 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010432 mWindow->consumeFocusEvent(false);
10433
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010434 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010435 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10436 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
10437 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +000010438 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010440 // Key will not go to window because we have no focused window.
10441 // The 'no focused window' ANR timer should start instead.
10442
10443 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010444 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010445 // The key should get dropped and there should be no ANR.
10446
10447 ASSERT_TRUE(mDispatcher->waitForIdle());
10448 mFakePolicy->assertNotifyAnrWasNotCalled();
10449}
10450
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010451// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010452// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10453// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010454TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010455 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010456 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10457 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010458
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010459 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010460 ASSERT_TRUE(sequenceNum);
10461 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010462 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010463
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010464 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010465 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010466 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010467 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010468 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010469}
10470
10471// Send a key to the app and have the app not respond right away.
10472TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
10473 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010475 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010476 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010477 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010478 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010479 ASSERT_TRUE(mDispatcher->waitForIdle());
10480}
10481
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010482// We have a focused application, but no focused window
10483TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010484 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010485 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010486 mWindow->consumeFocusEvent(false);
10487
10488 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010489 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010490 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10491 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010492 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10493 mDispatcher->waitForIdle();
10494 mFakePolicy->assertNotifyAnrWasNotCalled();
10495
10496 // Once a focused event arrives, we get an ANR for this application
10497 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10498 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010499 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010500 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10501 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +080010502 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010503 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010504 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -070010505 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010506 ASSERT_TRUE(mDispatcher->waitForIdle());
10507}
10508
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010509/**
10510 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
10511 * there will not be an ANR.
10512 */
10513TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
10514 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010515 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010516 mWindow->consumeFocusEvent(false);
10517
10518 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -070010519 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
10520 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010521 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
10522 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
10523
10524 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010525 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
10526 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
10527 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
10528 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010529
Hu Guofe3c8f12023-09-22 17:20:15 +080010530 const int32_t policyFlags =
10531 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010532
10533 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +000010534 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010535 InputEventInjectionSync::WAIT_FOR_RESULT,
10536 INJECT_EVENT_TIMEOUT, policyFlags);
10537 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
10538 << "Injection should fail because the event is stale";
10539
10540 ASSERT_TRUE(mDispatcher->waitForIdle());
10541 mFakePolicy->assertNotifyAnrWasNotCalled();
10542 mWindow->assertNoEvents();
10543}
10544
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010545// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010546// Make sure that we don't notify policy twice about the same ANR.
10547TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010548 const std::chrono::duration appTimeout = 400ms;
10549 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010550 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010551
Vishnu Nair47074b82020-08-14 11:54:47 -070010552 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010553 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010554 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010555
10556 // Once a focused event arrives, we get an ANR for this application
10557 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10558 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010559 const std::chrono::duration eventInjectionTimeout = 100ms;
10560 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010561 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010562 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10563 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
10564 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010565 /*allowKeyRepeat=*/false);
10566 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
10567 << "result=" << ftl::enum_string(result);
10568 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
10569 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
10570 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
10571 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010572
Vishnu Naire4df8752022-09-08 09:17:55 -070010573 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010574 // ANR should not be raised again. It is up to policy to do that if it desires.
10575 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010576
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010577 // If we now get a focused window, the ANR should stop, but the policy handles that via
10578 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010579 ASSERT_TRUE(mDispatcher->waitForIdle());
10580}
10581
10582// We have a focused application, but no focused window
10583TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010584 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010585 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010586 mWindow->consumeFocusEvent(false);
10587
10588 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010589 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010590
Vishnu Naire4df8752022-09-08 09:17:55 -070010591 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10592 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010593
10594 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010595 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010596 ASSERT_TRUE(mDispatcher->waitForIdle());
10597 mWindow->assertNoEvents();
10598}
10599
10600/**
10601 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
10602 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
10603 * If we process 1 of the events, but ANR on the second event with the same timestamp,
10604 * the ANR mechanism should still work.
10605 *
10606 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
10607 * DOWN event, while not responding on the second one.
10608 */
10609TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
10610 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010611 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010612 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010613 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10614 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010615 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010616
10617 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010618 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010619 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010620 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10621 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010622 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010623
10624 // 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 -070010625 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010626 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010627 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010628}
10629
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010630// A spy window can receive an ANR
10631TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
10632 sp<FakeWindowHandle> spy = addSpyWindow();
10633
10634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010635 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10636 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010637 mWindow->consumeMotionDown();
10638
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010639 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010640 ASSERT_TRUE(sequenceNum);
10641 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010642 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010643
10644 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010645 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010646 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010647 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010648 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010649}
10650
10651// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010652// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010653TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10654 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010655
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010657 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10658 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10660 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010661
10662 // Stuck on the ACTION_UP
10663 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010664 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010665
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010666 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010667 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010668 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10669 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010670
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010671 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010672 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010673 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010674 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010675 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010676}
10677
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010678// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010679// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010680TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10681 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010682
10683 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010684 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10685 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010686
10687 mWindow->consumeMotionDown();
10688 // Stuck on the ACTION_UP
10689 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010690 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010691
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010692 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010693 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010694 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10695 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010696
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010697 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010698 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010699 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010700 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010701 spy->assertNoEvents();
10702}
10703
10704TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010705 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010706
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010707 FakeMonitorReceiver monitor =
10708 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010709
10710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10712 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010713
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010714 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010715 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10716 ASSERT_TRUE(consumeSeq);
10717
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010718 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10719 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010720
10721 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010722 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010723
10724 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010725 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010726}
10727
10728// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10729// process events, you don't get an anr. When the window later becomes unresponsive again, you
10730// get an ANR again.
10731// 1. tap -> block on ACTION_UP -> receive ANR
10732// 2. consume all pending events (= queue becomes healthy again)
10733// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10734TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10735 tapOnWindow();
10736
10737 mWindow->consumeMotionDown();
10738 // Block on ACTION_UP
10739 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010740 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010741 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10742 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010743 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010744 mWindow->assertNoEvents();
10745
10746 tapOnWindow();
10747 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010748 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010749 mWindow->consumeMotionUp();
10750
10751 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010752 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010753 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010754 mWindow->assertNoEvents();
10755}
10756
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010757// If a connection remains unresponsive for a while, make sure policy is only notified once about
10758// it.
10759TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010761 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10762 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010763
10764 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010765 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010766 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010767 // 'notifyConnectionUnresponsive' should only be called once per connection
10768 mFakePolicy->assertNotifyAnrWasNotCalled();
10769 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010770 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010771 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010772 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010773 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010774 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010775 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010776 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010777}
10778
10779/**
10780 * 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 -070010781 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010782 */
10783TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010784 // The timeouts in this test are established by relying on the fact that the "key waiting for
10785 // events timeout" is equal to 500ms.
10786 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010787 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010788 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010789
10790 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010791 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010792 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010793 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010794 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010795
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010796 // Don't finish the events yet, and send a key
10797 mDispatcher->notifyKey(
10798 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10799 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10800 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010801 // Key will not be sent to the window, yet, because the window is still processing events
10802 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010803 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010804 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010805
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010806 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010807 // if we wait long enough though, dispatcher will give up, and still send the key
10808 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010809 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010810 mWindow->finishEvent(*downSequenceNum);
10811 mWindow->finishEvent(*upSequenceNum);
10812}
10813
10814/**
10815 * If a window is processing a motion event, and then a key event comes in, the key event should
10816 * not go to the focused window until the motion is processed.
10817 * If then a new motion comes in, then the pending key event should be going to the currently
10818 * focused window right away.
10819 */
10820TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010821 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10822 // The timeouts in this test are established by relying on the fact that the "key waiting for
10823 // events timeout" is equal to 500ms.
10824 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010825 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010826 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010827
10828 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010829 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010830 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010831 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010832 ASSERT_TRUE(upSequenceNum);
10833 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010834 mDispatcher->notifyKey(
10835 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10836 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10837 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010838 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010839 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010840
10841 // Now tap down again. It should cause the pending key to go to the focused window right away.
10842 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010843 // Now that we tapped, we should receive the key immediately.
10844 // Since there's still room for slowness, we use 200ms, which is much less than
10845 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10846 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10847 ASSERT_NE(nullptr, keyEvent);
10848 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10849 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10850 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10851 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010852 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10853 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010854 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10855 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010856 mWindow->assertNoEvents();
10857}
10858
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010859/**
10860 * Send an event to the app and have the app not respond right away.
10861 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10862 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10863 * At some point, the window becomes responsive again.
10864 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10865 */
10866TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10868 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10869 .build());
10870
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010871 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010872 ASSERT_TRUE(sequenceNum);
10873 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10874 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10875
10876 mWindow->finishEvent(*sequenceNum);
10877 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10878 ASSERT_TRUE(mDispatcher->waitForIdle());
10879 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10880
10881 // Now that the window is responsive, let's continue the gesture.
10882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10883 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10884 .build());
10885
10886 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10887 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10888 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10889 .build());
10890
10891 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10892 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10893 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10894 .build());
10895 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10896 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10897 .build());
10898 // We already canceled this pointer, so the window shouldn't get any new events.
10899 mWindow->assertNoEvents();
10900
10901 // Start another one.
10902 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10903 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10904 .build());
10905 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10906}
10907
Prabir Pradhanfc364722024-02-08 17:51:20 +000010908// Send an event to the app and have the app not respond right away. Then remove the app window.
10909// When the window is removed, the dispatcher will cancel the events for that window.
10910// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10911TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10912 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010913 AINPUT_SOURCE_TOUCHSCREEN,
10914 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010915
10916 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10917 ASSERT_TRUE(sequenceNum);
10918
10919 // Remove the window, but the input channel should remain alive.
10920 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10921
10922 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10923 // Since the window was removed, Dispatcher does not know the PID associated with the window
10924 // anymore, so the policy is notified without the PID.
10925 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10926 /*pid=*/std::nullopt);
10927
10928 mWindow->finishEvent(*sequenceNum);
10929 // The cancellation was generated when the window was removed, along with the focus event.
10930 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010931 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010932 mWindow->consumeFocusEvent(false);
10933 ASSERT_TRUE(mDispatcher->waitForIdle());
10934 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10935}
10936
10937// Send an event to the app and have the app not respond right away. Wait for the policy to be
10938// notified of the unresponsive window, then remove the app window.
10939TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10940 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010941 AINPUT_SOURCE_TOUCHSCREEN,
10942 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010943
10944 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10945 ASSERT_TRUE(sequenceNum);
10946 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10947 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10948
10949 // Remove the window, but the input channel should remain alive.
10950 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10951
10952 mWindow->finishEvent(*sequenceNum);
10953 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10954 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010955 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010956 mWindow->consumeFocusEvent(false);
10957 ASSERT_TRUE(mDispatcher->waitForIdle());
10958 // Since the window was removed, Dispatcher does not know the PID associated with the window
10959 // becoming responsive, so the policy is notified without the PID.
10960 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10961}
10962
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010963class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10964 virtual void SetUp() override {
10965 InputDispatcherTest::SetUp();
10966
Chris Yea209fde2020-07-22 13:54:51 -070010967 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010968 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010969 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010970 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010971 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010972 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010973 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010974
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010975 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010976 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010977 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010978 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010979
10980 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010981 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010982 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010983
10984 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010985 mDispatcher->onWindowInfosChanged(
10986 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010987 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010988 mFocusedWindow->consumeFocusEvent(true);
10989 }
10990
10991 virtual void TearDown() override {
10992 InputDispatcherTest::TearDown();
10993
10994 mUnfocusedWindow.clear();
10995 mFocusedWindow.clear();
10996 }
10997
10998protected:
Chris Yea209fde2020-07-22 13:54:51 -070010999 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011000 sp<FakeWindowHandle> mUnfocusedWindow;
11001 sp<FakeWindowHandle> mFocusedWindow;
11002 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
11003 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
11004 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
11005
11006 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
11007
11008 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
11009
11010private:
11011 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011012 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011013 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11014 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011016 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11017 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011018 }
11019};
11020
11021// If we have 2 windows that are both unresponsive, the one with the shortest timeout
11022// should be ANR'd first.
11023TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011025 injectMotionEvent(*mDispatcher,
11026 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11027 AINPUT_SOURCE_TOUCHSCREEN)
11028 .pointer(PointerBuilder(0, ToolType::FINGER)
11029 .x(FOCUSED_WINDOW_LOCATION.x)
11030 .y(FOCUSED_WINDOW_LOCATION.y))
11031 .build()));
11032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11033 injectMotionEvent(*mDispatcher,
11034 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
11035 AINPUT_SOURCE_TOUCHSCREEN)
11036 .pointer(PointerBuilder(0, ToolType::FINGER)
11037 .x(FOCUSED_WINDOW_LOCATION.x)
11038 .y(FOCUSED_WINDOW_LOCATION.y))
11039 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011040 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011041 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011042 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011043 // We consumed all events, so no ANR
11044 ASSERT_TRUE(mDispatcher->waitForIdle());
11045 mFakePolicy->assertNotifyAnrWasNotCalled();
11046
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011047 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011048 injectMotionEvent(*mDispatcher,
11049 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11050 AINPUT_SOURCE_TOUCHSCREEN)
11051 .pointer(PointerBuilder(0, ToolType::FINGER)
11052 .x(FOCUSED_WINDOW_LOCATION.x)
11053 .y(FOCUSED_WINDOW_LOCATION.y))
11054 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011055 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011056 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011057
11058 const std::chrono::duration timeout =
11059 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011060 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011061
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011062 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011063 mFocusedWindow->consumeMotionDown();
11064 // This cancel is generated because the connection was unresponsive
11065 mFocusedWindow->consumeMotionCancel();
11066 mFocusedWindow->assertNoEvents();
11067 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011068 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080011069 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11070 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011071 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011072}
11073
11074// If we have 2 windows with identical timeouts that are both unresponsive,
11075// it doesn't matter which order they should have ANR.
11076// But we should receive ANR for both.
11077TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
11078 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011079 mUnfocusedWindow->setDispatchingTimeout(
11080 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011081 mDispatcher->onWindowInfosChanged(
11082 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011083
11084 tapOnFocusedWindow();
11085 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011086 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011087 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
11088 mFocusedWindow->getDispatchingTimeout(
11089 DISPATCHING_TIMEOUT)),
11090 mFakePolicy->getUnresponsiveWindowToken(0ms)};
11091
11092 ASSERT_THAT(anrConnectionTokens,
11093 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11094 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011095
11096 ASSERT_TRUE(mDispatcher->waitForIdle());
11097 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011098
11099 mFocusedWindow->consumeMotionDown();
11100 mFocusedWindow->consumeMotionUp();
11101 mUnfocusedWindow->consumeMotionOutside();
11102
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011103 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
11104 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011105
11106 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011107 ASSERT_THAT(responsiveTokens,
11108 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11109 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011110 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011111}
11112
11113// If a window is already not responding, the second tap on the same window should be ignored.
11114// We should also log an error to account for the dropped event (not tested here).
11115// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
11116TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
11117 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011118 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011119 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011120 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011121 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011122 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011123 ASSERT_TRUE(upEventSequenceNum);
11124 const std::chrono::duration timeout =
11125 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011126 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011127
11128 // Tap once again
11129 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011130 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011131 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11132 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011133 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011134 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011135 FOCUSED_WINDOW_LOCATION));
11136 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
11137 // valid touch target
11138 mUnfocusedWindow->assertNoEvents();
11139
11140 // Consume the first tap
11141 mFocusedWindow->finishEvent(*downEventSequenceNum);
11142 mFocusedWindow->finishEvent(*upEventSequenceNum);
11143 ASSERT_TRUE(mDispatcher->waitForIdle());
11144 // The second tap did not go to the focused window
11145 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011146 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080011147 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11148 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011149 mFakePolicy->assertNotifyAnrWasNotCalled();
11150}
11151
11152// If you tap outside of all windows, there will not be ANR
11153TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011154 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011155 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11156 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011157 ASSERT_TRUE(mDispatcher->waitForIdle());
11158 mFakePolicy->assertNotifyAnrWasNotCalled();
11159}
11160
11161// Since the focused window is paused, tapping on it should not produce any events
11162TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
11163 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011164 mDispatcher->onWindowInfosChanged(
11165 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011166
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011167 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011168 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11169 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011170
11171 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
11172 ASSERT_TRUE(mDispatcher->waitForIdle());
11173 // Should not ANR because the window is paused, and touches shouldn't go to it
11174 mFakePolicy->assertNotifyAnrWasNotCalled();
11175
11176 mFocusedWindow->assertNoEvents();
11177 mUnfocusedWindow->assertNoEvents();
11178}
11179
11180/**
11181 * 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 -070011182 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011183 * If a different window becomes focused at this time, the key should go to that window instead.
11184 *
11185 * Warning!!!
11186 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
11187 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011188 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011189 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
11190 *
11191 * If that value changes, this test should also change.
11192 */
11193TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
11194 // Set a long ANR timeout to prevent it from triggering
11195 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011196 mDispatcher->onWindowInfosChanged(
11197 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011198
11199 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011200 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011201 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011202 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011203 ASSERT_TRUE(upSequenceNum);
11204 // Don't finish the events yet, and send a key
11205 // Injection will succeed because we will eventually give up and send the key to the focused
11206 // window even if motions are still being processed.
11207
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011208 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011209 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11210 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011211 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011213 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011214 // and the key remains pending, waiting for the touch events to be processed.
11215 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
11216 // under the hood.
11217 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
11218 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011219
11220 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070011221 mFocusedWindow->setFocusable(false);
11222 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011223 mDispatcher->onWindowInfosChanged(
11224 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011225 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011226
11227 // Focus events should precede the key events
11228 mUnfocusedWindow->consumeFocusEvent(true);
11229 mFocusedWindow->consumeFocusEvent(false);
11230
11231 // Finish the tap events, which should unblock dispatcher
11232 mUnfocusedWindow->finishEvent(*downSequenceNum);
11233 mUnfocusedWindow->finishEvent(*upSequenceNum);
11234
11235 // Now that all queues are cleared and no backlog in the connections, the key event
11236 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011237 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011238 mFocusedWindow->assertNoEvents();
11239 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011240 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011241}
11242
11243// When the touch stream is split across 2 windows, and one of them does not respond,
11244// then ANR should be raised and the touch should be canceled for the unresponsive window.
11245// The other window should not be affected by that.
11246TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
11247 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011248 mDispatcher->notifyMotion(
11249 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11250 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
11251 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011252
11253 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000011254 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011255 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11256 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011257 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011258
11259 const std::chrono::duration timeout =
11260 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011261 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011262
11263 mUnfocusedWindow->consumeMotionDown();
11264 mFocusedWindow->consumeMotionDown();
11265 // Focused window may or may not receive ACTION_MOVE
11266 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011267 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011268 ASSERT_TRUE(moveOrCancelSequenceNum);
11269 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
11270 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070011271 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011272 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
11273 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
11274 mFocusedWindow->consumeMotionCancel();
11275 } else {
11276 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
11277 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011278 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080011279 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11280 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011281
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011282 mUnfocusedWindow->assertNoEvents();
11283 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011284 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011285}
11286
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011287/**
11288 * If we have no focused window, and a key comes in, we start the ANR timer.
11289 * The focused application should add a focused window before the timer runs out to prevent ANR.
11290 *
11291 * If the user touches another application during this time, the key should be dropped.
11292 * Next, if a new focused window comes in, without toggling the focused application,
11293 * then no ANR should occur.
11294 *
11295 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
11296 * but in some cases the policy may not update the focused application.
11297 */
11298TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
11299 std::shared_ptr<FakeApplicationHandle> focusedApplication =
11300 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070011301 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011302 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011303 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
11304 mFocusedWindow->setFocusable(false);
11305
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011306 mDispatcher->onWindowInfosChanged(
11307 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011308 mFocusedWindow->consumeFocusEvent(false);
11309
11310 // Send a key. The ANR timer should start because there is no focused window.
11311 // 'focusedApplication' will get blamed if this timer completes.
11312 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011313 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011314 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11315 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011316 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000011317 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011318 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011319
11320 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
11321 // then the injected touches won't cause the focused event to get dropped.
11322 // The dispatcher only checks for whether the queue should be pruned upon queueing.
11323 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
11324 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
11325 // For this test, it means that the key would get delivered to the window once it becomes
11326 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011327 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011328
11329 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011330 mDispatcher->notifyMotion(
11331 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11332 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011333
11334 // We do not consume the motion right away, because that would require dispatcher to first
11335 // process (== drop) the key event, and by that time, ANR will be raised.
11336 // Set the focused window first.
11337 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011338 mDispatcher->onWindowInfosChanged(
11339 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011340 setFocusedWindow(mFocusedWindow);
11341 mFocusedWindow->consumeFocusEvent(true);
11342 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
11343 // to another application. This could be a bug / behaviour in the policy.
11344
11345 mUnfocusedWindow->consumeMotionDown();
11346
11347 ASSERT_TRUE(mDispatcher->waitForIdle());
11348 // Should not ANR because we actually have a focused window. It was just added too slowly.
11349 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
11350}
11351
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011352/**
11353 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
11354 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
11355 * dispatcher doesn't prune pointer events incorrectly.
11356 *
11357 * This test reproduces a crash in InputDispatcher.
11358 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
11359 *
11360 * Keep the currently focused application (mApplication), and have no focused window.
11361 * We set up two additional windows:
11362 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
11363 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
11364 * window. This window is not focusable, but is touchable.
11365 *
11366 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
11367 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
11368 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
11369 *
11370 * Now, we touch "Another window". This window is owned by a different application than
11371 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
11372 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
11373 * dropping the events from its queue. Ensure that no crash occurs.
11374 *
11375 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
11376 * This does not affect the test running time.
11377 */
11378TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
11379 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
11380 std::make_shared<FakeApplicationHandle>();
11381 systemUiApplication->setDispatchingTimeout(3000ms);
11382 mFakePolicy->setStaleEventTimeout(3000ms);
11383 sp<FakeWindowHandle> navigationBar =
11384 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011385 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011386 navigationBar->setFocusable(false);
11387 navigationBar->setWatchOutsideTouch(true);
11388 navigationBar->setFrame(Rect(0, 0, 100, 100));
11389
11390 mApplication->setDispatchingTimeout(3000ms);
11391 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011392 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011393
11394 std::shared_ptr<FakeApplicationHandle> anotherApplication =
11395 std::make_shared<FakeApplicationHandle>();
11396 sp<FakeWindowHandle> appWindow =
11397 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011398 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011399 appWindow->setFocusable(false);
11400 appWindow->setFrame(Rect(100, 100, 200, 200));
11401
11402 mDispatcher->onWindowInfosChanged(
11403 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
11404 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
11405 mFocusedWindow->consumeFocusEvent(false);
11406
11407 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
11408 // in response.
11409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11410 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11411 .build());
11412 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11413
11414 // Key will not be sent anywhere because we have no focused window. It will remain pending.
11415 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
11416 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011417 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11418 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011419 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011420 /*allowKeyRepeat=*/false);
11421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11422
11423 // Finish the gesture - lift up finger and inject ACTION_UP key event
11424 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11425 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11426 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011427 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
11428 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011429 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011430 /*allowKeyRepeat=*/false);
11431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11432 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
11433 // getting any events yet.
11434 navigationBar->assertNoEvents();
11435
11436 // Now touch "Another window". This touch is going to a different application than the one we
11437 // are waiting for (which is 'mApplication').
11438 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
11439 // trying to be injected) and to continue processing the rest of the events in the original
11440 // order.
11441 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11442 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
11443 .build());
11444 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
11445 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
11446 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11447
11448 appWindow->assertNoEvents();
11449 navigationBar->assertNoEvents();
11450}
11451
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011452// These tests ensure we cannot send touch events to a window that's positioned behind a window
11453// that has feature NO_INPUT_CHANNEL.
11454// Layout:
11455// Top (closest to user)
11456// mNoInputWindow (above all windows)
11457// mBottomWindow
11458// Bottom (furthest from user)
11459class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
11460 virtual void SetUp() override {
11461 InputDispatcherTest::SetUp();
11462
11463 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011464 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11465 "Window without input channel",
11466 ui::LogicalDisplayId::DEFAULT,
11467 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011468 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011469 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
11470 // It's perfectly valid for this window to not have an associated input channel
11471
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011472 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011473 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011474 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
11475
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011476 mDispatcher->onWindowInfosChanged(
11477 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011478 }
11479
11480protected:
11481 std::shared_ptr<FakeApplicationHandle> mApplication;
11482 sp<FakeWindowHandle> mNoInputWindow;
11483 sp<FakeWindowHandle> mBottomWindow;
11484};
11485
11486TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
11487 PointF touchedPoint = {10, 10};
11488
Prabir Pradhan678438e2023-04-13 19:32:51 +000011489 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011490 AINPUT_SOURCE_TOUCHSCREEN,
11491 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011492
11493 mNoInputWindow->assertNoEvents();
11494 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
11495 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
11496 // and therefore should prevent mBottomWindow from receiving touches
11497 mBottomWindow->assertNoEvents();
11498}
11499
11500/**
11501 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
11502 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
11503 */
11504TEST_F(InputDispatcherMultiWindowOcclusionTests,
11505 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011506 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11507 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011508 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011509
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011510 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011511 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011512 mDispatcher->onWindowInfosChanged(
11513 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011514
11515 PointF touchedPoint = {10, 10};
11516
Prabir Pradhan678438e2023-04-13 19:32:51 +000011517 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011518 AINPUT_SOURCE_TOUCHSCREEN,
11519 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011520
11521 mNoInputWindow->assertNoEvents();
11522 mBottomWindow->assertNoEvents();
11523}
11524
Vishnu Nair958da932020-08-21 17:12:37 -070011525class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
11526protected:
11527 std::shared_ptr<FakeApplicationHandle> mApp;
11528 sp<FakeWindowHandle> mWindow;
11529 sp<FakeWindowHandle> mMirror;
11530
11531 virtual void SetUp() override {
11532 InputDispatcherTest::SetUp();
11533 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011534 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11535 ui::LogicalDisplayId::DEFAULT);
11536 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
11537 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070011538 mWindow->setFocusable(true);
11539 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011540 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011541 }
11542};
11543
11544TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
11545 // Request focus on a mirrored window
11546 setFocusedWindow(mMirror);
11547
11548 // window gets focused
11549 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011551 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011552 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011553}
11554
11555// A focused & mirrored window remains focused only if the window and its mirror are both
11556// focusable.
11557TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
11558 setFocusedWindow(mMirror);
11559
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000011560 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070011561 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011562 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011563 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011564 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011565 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011566 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011567 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011568
11569 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011570 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011571
11572 // window loses focus since one of the windows associated with the token in not focusable
11573 mWindow->consumeFocusEvent(false);
11574
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011575 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011576 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011577 mWindow->assertNoEvents();
11578}
11579
11580// A focused & mirrored window remains focused until the window and its mirror both become
11581// invisible.
11582TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
11583 setFocusedWindow(mMirror);
11584
11585 // window gets focused
11586 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011588 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011589 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011590 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011591 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011592 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011593
11594 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011595 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011596
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011598 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011599 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011600 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011601 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011602 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011603
11604 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011605 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011606
11607 // window loses focus only after all windows associated with the token become invisible.
11608 mWindow->consumeFocusEvent(false);
11609
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011610 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011611 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011612 mWindow->assertNoEvents();
11613}
11614
11615// A focused & mirrored window remains focused until both windows are removed.
11616TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
11617 setFocusedWindow(mMirror);
11618
11619 // window gets focused
11620 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011622 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011623 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011625 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011626 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011627
11628 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011629 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011630
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011632 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011633 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011635 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011636 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011637
11638 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011639 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011640 mWindow->consumeFocusEvent(false);
11641
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011642 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011643 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011644 mWindow->assertNoEvents();
11645}
11646
11647// Focus request can be pending until one window becomes visible.
11648TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11649 // Request focus on an invisible mirror.
11650 mWindow->setVisible(false);
11651 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011652 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011653 setFocusedWindow(mMirror);
11654
11655 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011657 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011658 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070011659
11660 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011661 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011662
11663 // window gets focused
11664 mWindow->consumeFocusEvent(true);
11665 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011666 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070011667}
Prabir Pradhan99987712020-11-10 18:43:05 -080011668
11669class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11670protected:
11671 std::shared_ptr<FakeApplicationHandle> mApp;
11672 sp<FakeWindowHandle> mWindow;
11673 sp<FakeWindowHandle> mSecondWindow;
11674
11675 void SetUp() override {
11676 InputDispatcherTest::SetUp();
11677 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011678 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11679 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011680 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011681 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11682 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011683 mSecondWindow->setFocusable(true);
11684
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011685 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011686 mDispatcher->onWindowInfosChanged(
11687 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080011688
11689 setFocusedWindow(mWindow);
11690 mWindow->consumeFocusEvent(true);
11691 }
11692
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011693 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011694 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011695 }
11696
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011697 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11698 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011699 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011700 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011701 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011702 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011703 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011704 }
11705};
11706
11707TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11708 // Ensure that capture cannot be obtained for unfocused windows.
11709 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11710 mFakePolicy->assertSetPointerCaptureNotCalled();
11711 mSecondWindow->assertNoEvents();
11712
11713 // Ensure that capture can be enabled from the focus window.
11714 requestAndVerifyPointerCapture(mWindow, true);
11715
11716 // Ensure that capture cannot be disabled from a window that does not have capture.
11717 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11718 mFakePolicy->assertSetPointerCaptureNotCalled();
11719
11720 // Ensure that capture can be disabled from the window with capture.
11721 requestAndVerifyPointerCapture(mWindow, false);
11722}
11723
11724TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011725 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011726
11727 setFocusedWindow(mSecondWindow);
11728
11729 // Ensure that the capture disabled event was sent first.
11730 mWindow->consumeCaptureEvent(false);
11731 mWindow->consumeFocusEvent(false);
11732 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011733 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011734
11735 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011736 notifyPointerCaptureChanged({});
11737 notifyPointerCaptureChanged(request);
11738 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011739 mWindow->assertNoEvents();
11740 mSecondWindow->assertNoEvents();
11741 mFakePolicy->assertSetPointerCaptureNotCalled();
11742}
11743
11744TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011745 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011746
11747 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011748 notifyPointerCaptureChanged({});
11749 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011750
11751 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011752 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011753 mWindow->consumeCaptureEvent(false);
11754 mWindow->assertNoEvents();
11755}
11756
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011757TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11758 requestAndVerifyPointerCapture(mWindow, true);
11759
11760 // The first window loses focus.
11761 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011762 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011763 mWindow->consumeCaptureEvent(false);
11764
11765 // Request Pointer Capture from the second window before the notification from InputReader
11766 // arrives.
11767 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011768 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011769
11770 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011771 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011772
11773 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011774 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011775
11776 mSecondWindow->consumeFocusEvent(true);
11777 mSecondWindow->consumeCaptureEvent(true);
11778}
11779
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011780TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11781 // App repeatedly enables and disables capture.
11782 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011783 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011784 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011785 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011786 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011787 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011788
11789 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11790 // first request is now stale, this should do nothing.
11791 notifyPointerCaptureChanged(firstRequest);
11792 mWindow->assertNoEvents();
11793
11794 // InputReader notifies that the second request was enabled.
11795 notifyPointerCaptureChanged(secondRequest);
11796 mWindow->consumeCaptureEvent(true);
11797}
11798
Prabir Pradhan7092e262022-05-03 16:51:09 +000011799TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11800 requestAndVerifyPointerCapture(mWindow, true);
11801
11802 // App toggles pointer capture off and on.
11803 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011804 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011805
11806 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011807 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011808
11809 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11810 // preceding "disable" request.
11811 notifyPointerCaptureChanged(enableRequest);
11812
11813 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11814 // any notifications.
11815 mWindow->assertNoEvents();
11816}
11817
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011818/**
11819 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11820 * mouse movements don't affect the previous mouse hovering state.
11821 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11822 * HOVER_MOVE events).
11823 */
11824TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11825 // Mouse hover on the window
11826 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11827 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11828 .build());
11829 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11830 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11831 .build());
11832
11833 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11834 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11835
11836 // Start pointer capture
11837 requestAndVerifyPointerCapture(mWindow, true);
11838
11839 // Send some relative mouse movements and receive them in the window.
11840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11842 .build());
11843 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11844 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11845
11846 // Stop pointer capture
11847 requestAndVerifyPointerCapture(mWindow, false);
11848
11849 // Continue hovering on the window
11850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11851 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11852 .build());
11853 mWindow->consumeMotionEvent(
11854 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11855
11856 mWindow->assertNoEvents();
11857}
11858
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011859TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11860 // The default display is the focused display to begin with.
11861 requestAndVerifyPointerCapture(mWindow, true);
11862
11863 // Move the second window to a second display, make it the focused window on that display.
11864 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11865 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11866 setFocusedWindow(mSecondWindow);
11867 mSecondWindow->consumeFocusEvent(true);
11868
11869 mWindow->assertNoEvents();
11870
11871 // The second window cannot gain capture because it is not on the focused display.
11872 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11873 mFakePolicy->assertSetPointerCaptureNotCalled();
11874 mSecondWindow->assertNoEvents();
11875
11876 // Make the second display the focused display.
11877 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011878 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011879
11880 // This causes the first window to lose pointer capture, and it's unable to request capture.
11881 mWindow->consumeCaptureEvent(false);
11882 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11883
11884 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11885 mFakePolicy->assertSetPointerCaptureNotCalled();
11886
11887 // The second window is now able to gain pointer capture successfully.
11888 requestAndVerifyPointerCapture(mSecondWindow, true);
11889}
11890
Hiroki Sato25040232024-02-22 17:21:22 +090011891using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11892
11893TEST_F(InputDispatcherPointerCaptureDeathTest,
11894 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11895 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11896 ScopedSilentDeath _silentDeath;
11897
11898 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11899 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11900
11901 // Dispatch a pointer changed event with a wrong token.
11902 request.window = mSecondWindow->getToken();
11903 ASSERT_DEATH(
11904 {
11905 notifyPointerCaptureChanged(request);
11906 mSecondWindow->consumeCaptureEvent(true);
11907 },
11908 "Unexpected requested window for Pointer Capture.");
11909}
11910
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011911class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11912protected:
11913 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011914
11915 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11916 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11917
11918 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11919 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11920
11921 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11922 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11923 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11924 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11925 MAXIMUM_OBSCURING_OPACITY);
11926
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011927 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11928 static constexpr gui::Uid APP_B_UID{10002};
11929 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011930
11931 sp<FakeWindowHandle> mTouchWindow;
11932
11933 virtual void SetUp() override {
11934 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011935 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011936 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11937 }
11938
11939 virtual void TearDown() override {
11940 InputDispatcherTest::TearDown();
11941 mTouchWindow.clear();
11942 }
11943
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011944 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011945 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011946 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011947 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011948 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011949 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011950 return window;
11951 }
11952
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011953 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011954 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11955 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011956 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011957 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011958 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011959 return window;
11960 }
11961
11962 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011963 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011964 AINPUT_SOURCE_TOUCHSCREEN,
11965 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011966 }
11967};
11968
11969TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011970 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011971 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011972 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011973
11974 touch();
11975
11976 mTouchWindow->assertNoEvents();
11977}
11978
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011979TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011980 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11981 const sp<FakeWindowHandle>& w =
11982 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011983 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011984
11985 touch();
11986
11987 mTouchWindow->assertNoEvents();
11988}
11989
11990TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011991 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11992 const sp<FakeWindowHandle>& w =
11993 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011994 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011995
11996 touch();
11997
11998 w->assertNoEvents();
11999}
12000
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012001TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012002 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012003 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012004
12005 touch();
12006
12007 mTouchWindow->consumeAnyMotionDown();
12008}
12009
12010TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012011 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012012 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012013 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012014 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012015
12016 touch({PointF{100, 100}});
12017
12018 mTouchWindow->consumeAnyMotionDown();
12019}
12020
12021TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012022 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012023 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012024 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012025
12026 touch();
12027
12028 mTouchWindow->consumeAnyMotionDown();
12029}
12030
12031TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
12032 const sp<FakeWindowHandle>& w =
12033 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012034 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012035
12036 touch();
12037
12038 mTouchWindow->consumeAnyMotionDown();
12039}
12040
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012041TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
12042 const sp<FakeWindowHandle>& w =
12043 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012044 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012045
12046 touch();
12047
12048 w->assertNoEvents();
12049}
12050
12051/**
12052 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
12053 * inside) while letting them pass-through. Note that even though touch passes through the occluding
12054 * window, the occluding window will still receive ACTION_OUTSIDE event.
12055 */
12056TEST_F(InputDispatcherUntrustedTouchesTest,
12057 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
12058 const sp<FakeWindowHandle>& w =
12059 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012060 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012061 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012062
12063 touch();
12064
12065 w->consumeMotionOutside();
12066}
12067
12068TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
12069 const sp<FakeWindowHandle>& w =
12070 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012071 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012072 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012073
12074 touch();
12075
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012076 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000012077}
12078
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012079TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012080 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012081 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12082 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012083 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012084
12085 touch();
12086
12087 mTouchWindow->consumeAnyMotionDown();
12088}
12089
12090TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
12091 const sp<FakeWindowHandle>& w =
12092 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12093 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012094 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012095
12096 touch();
12097
12098 mTouchWindow->consumeAnyMotionDown();
12099}
12100
12101TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012102 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012103 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12104 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012105 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012106
12107 touch();
12108
12109 mTouchWindow->assertNoEvents();
12110}
12111
12112TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
12113 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
12114 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012115 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12116 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012117 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012118 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12119 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012120 mDispatcher->onWindowInfosChanged(
12121 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012122
12123 touch();
12124
12125 mTouchWindow->assertNoEvents();
12126}
12127
12128TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
12129 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
12130 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012131 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12132 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012133 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012134 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12135 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012136 mDispatcher->onWindowInfosChanged(
12137 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012138
12139 touch();
12140
12141 mTouchWindow->consumeAnyMotionDown();
12142}
12143
12144TEST_F(InputDispatcherUntrustedTouchesTest,
12145 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
12146 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012147 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12148 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012149 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012150 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12151 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012152 mDispatcher->onWindowInfosChanged(
12153 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012154
12155 touch();
12156
12157 mTouchWindow->consumeAnyMotionDown();
12158}
12159
12160TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
12161 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012162 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12163 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012164 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012165 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12166 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012167 mDispatcher->onWindowInfosChanged(
12168 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012169
12170 touch();
12171
12172 mTouchWindow->assertNoEvents();
12173}
12174
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012175TEST_F(InputDispatcherUntrustedTouchesTest,
12176 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
12177 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012178 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12179 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012180 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012181 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12182 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012183 mDispatcher->onWindowInfosChanged(
12184 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012185
12186 touch();
12187
12188 mTouchWindow->assertNoEvents();
12189}
12190
12191TEST_F(InputDispatcherUntrustedTouchesTest,
12192 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
12193 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012194 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12195 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012196 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012197 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12198 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012199 mDispatcher->onWindowInfosChanged(
12200 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012201
12202 touch();
12203
12204 mTouchWindow->consumeAnyMotionDown();
12205}
12206
12207TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
12208 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012209 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12210 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012211 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012212
12213 touch();
12214
12215 mTouchWindow->consumeAnyMotionDown();
12216}
12217
12218TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
12219 const sp<FakeWindowHandle>& w =
12220 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012221 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012222
12223 touch();
12224
12225 mTouchWindow->consumeAnyMotionDown();
12226}
12227
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012228TEST_F(InputDispatcherUntrustedTouchesTest,
12229 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
12230 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12231 const sp<FakeWindowHandle>& w =
12232 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012233 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012234
12235 touch();
12236
12237 mTouchWindow->assertNoEvents();
12238}
12239
12240TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
12241 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12242 const sp<FakeWindowHandle>& w =
12243 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012244 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012245
12246 touch();
12247
12248 mTouchWindow->consumeAnyMotionDown();
12249}
12250
12251TEST_F(InputDispatcherUntrustedTouchesTest,
12252 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
12253 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
12254 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012255 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12256 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012257 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012258
12259 touch();
12260
12261 mTouchWindow->consumeAnyMotionDown();
12262}
12263
12264TEST_F(InputDispatcherUntrustedTouchesTest,
12265 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
12266 const sp<FakeWindowHandle>& w1 =
12267 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12268 OPACITY_BELOW_THRESHOLD);
12269 const sp<FakeWindowHandle>& w2 =
12270 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12271 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012272 mDispatcher->onWindowInfosChanged(
12273 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012274
12275 touch();
12276
12277 mTouchWindow->assertNoEvents();
12278}
12279
12280/**
12281 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
12282 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
12283 * (which alone would result in allowing touches) does not affect the blocking behavior.
12284 */
12285TEST_F(InputDispatcherUntrustedTouchesTest,
12286 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
12287 const sp<FakeWindowHandle>& wB =
12288 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12289 OPACITY_BELOW_THRESHOLD);
12290 const sp<FakeWindowHandle>& wC =
12291 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12292 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012293 mDispatcher->onWindowInfosChanged(
12294 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012295
12296 touch();
12297
12298 mTouchWindow->assertNoEvents();
12299}
12300
12301/**
12302 * This test is testing that a window from a different UID but with same application token doesn't
12303 * block the touch. Apps can share the application token for close UI collaboration for example.
12304 */
12305TEST_F(InputDispatcherUntrustedTouchesTest,
12306 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
12307 const sp<FakeWindowHandle>& w =
12308 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
12309 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012310 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012311
12312 touch();
12313
12314 mTouchWindow->consumeAnyMotionDown();
12315}
12316
arthurhungb89ccb02020-12-30 16:19:01 +080012317class InputDispatcherDragTests : public InputDispatcherTest {
12318protected:
12319 std::shared_ptr<FakeApplicationHandle> mApp;
12320 sp<FakeWindowHandle> mWindow;
12321 sp<FakeWindowHandle> mSecondWindow;
12322 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012323 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012324 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
12325 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080012326
12327 void SetUp() override {
12328 InputDispatcherTest::SetUp();
12329 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012330 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12331 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080012332 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080012333
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012334 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12335 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080012336 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080012337
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012338 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
12339 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012340 mSpyWindow->setSpy(true);
12341 mSpyWindow->setTrustedOverlay(true);
12342 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
12343
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012344 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012345 mDispatcher->onWindowInfosChanged(
12346 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
12347 {},
12348 0,
12349 0});
arthurhungb89ccb02020-12-30 16:19:01 +080012350 }
12351
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012352 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
12353 switch (fromSource) {
12354 case AINPUT_SOURCE_TOUCHSCREEN:
12355 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012356 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012357 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012358 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12359 break;
12360 case AINPUT_SOURCE_STYLUS:
12361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012362 injectMotionEvent(*mDispatcher,
12363 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12364 AINPUT_SOURCE_STYLUS)
12365 .buttonState(
12366 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
12367 .pointer(PointerBuilder(0, ToolType::STYLUS)
12368 .x(50)
12369 .y(50))
12370 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012371 break;
12372 case AINPUT_SOURCE_MOUSE:
12373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012374 injectMotionEvent(*mDispatcher,
12375 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12376 AINPUT_SOURCE_MOUSE)
12377 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
12378 .pointer(PointerBuilder(MOUSE_POINTER_ID,
12379 ToolType::MOUSE)
12380 .x(50)
12381 .y(50))
12382 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012383 break;
12384 default:
12385 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
12386 }
arthurhungb89ccb02020-12-30 16:19:01 +080012387
12388 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012389 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012390 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012391 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012392 }
12393
12394 // Start performing drag, we will create a drag window and transfer touch to it.
12395 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
12396 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012397 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000012398 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012399 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000012400 }
arthurhungb89ccb02020-12-30 16:19:01 +080012401
12402 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012403 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
12404 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012405 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012406 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
12407 *mWindow->getInfo(), *mSecondWindow->getInfo()},
12408 {},
12409 0,
12410 0});
arthurhungb89ccb02020-12-30 16:19:01 +080012411
12412 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000012413 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000012414 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
12415 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000012416 if (transferred) {
12417 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012418 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12419 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012420 }
12421 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080012422 }
12423};
12424
12425TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012426 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080012427
12428 // Move on window.
12429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012430 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012431 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012432 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012433 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12434 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012435 mWindow->consumeDragEvent(false, 50, 50);
12436 mSecondWindow->assertNoEvents();
12437
12438 // Move to another window.
12439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012440 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012441 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012443 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12444 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012445 mWindow->consumeDragEvent(true, 150, 50);
12446 mSecondWindow->consumeDragEvent(false, 50, 50);
12447
12448 // Move back to original window.
12449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012450 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012451 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012452 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012453 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12454 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012455 mWindow->consumeDragEvent(false, 50, 50);
12456 mSecondWindow->consumeDragEvent(true, -50, 50);
12457
12458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012459 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012460 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012462 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012463 mWindow->assertNoEvents();
12464 mSecondWindow->assertNoEvents();
12465}
12466
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012467TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012468 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012469
12470 // No cancel event after drag start
12471 mSpyWindow->assertNoEvents();
12472
12473 const MotionEvent secondFingerDownEvent =
12474 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12475 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012476 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12477 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012478 .build();
12479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012480 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012481 InputEventInjectionSync::WAIT_FOR_RESULT))
12482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12483
12484 // Receives cancel for first pointer after next pointer down
12485 mSpyWindow->consumeMotionCancel();
12486 mSpyWindow->consumeMotionDown();
12487
12488 mSpyWindow->assertNoEvents();
12489}
12490
arthurhungf452d0b2021-01-06 00:19:52 +080012491TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012492 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080012493
12494 // Move on window.
12495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012496 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012497 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012498 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012499 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12500 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012501 mWindow->consumeDragEvent(false, 50, 50);
12502 mSecondWindow->assertNoEvents();
12503
12504 // Move to another window.
12505 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012506 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012507 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012508 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012509 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12510 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012511 mWindow->consumeDragEvent(true, 150, 50);
12512 mSecondWindow->consumeDragEvent(false, 50, 50);
12513
12514 // drop to another window.
12515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012516 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080012517 {150, 50}))
12518 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012519 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012520 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080012521 mWindow->assertNoEvents();
12522 mSecondWindow->assertNoEvents();
12523}
12524
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012525TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
12526 startDrag();
12527
12528 // No cancel event after drag start
12529 mSpyWindow->assertNoEvents();
12530
12531 const MotionEvent secondFingerDownEvent =
12532 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12533 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12534 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12535 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12536 .build();
12537 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12538 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12539 InputEventInjectionSync::WAIT_FOR_RESULT))
12540 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12541
12542 // Receives cancel for first pointer after next pointer down
12543 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080012544 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012545 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
12546
12547 mSpyWindow->assertNoEvents();
12548
12549 // Spy window calls pilfer pointers
12550 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
12551 mDragWindow->assertNoEvents();
12552
12553 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012554 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012555 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12556 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
12557 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12558 .build();
12559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012560 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012561 InputEventInjectionSync::WAIT_FOR_RESULT))
12562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12563
12564 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000012565 mDragWindow->consumeMotionEvent(
12566 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012567 mDragWindow->assertNoEvents();
12568}
12569
arthurhung6d4bed92021-03-17 11:59:33 +080012570TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012571 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080012572
12573 // Move on window and keep button pressed.
12574 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012575 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012576 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12577 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012578 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012579 .build()))
12580 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012581 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12582 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012583 mWindow->consumeDragEvent(false, 50, 50);
12584 mSecondWindow->assertNoEvents();
12585
12586 // Move to another window and release button, expect to drop item.
12587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012588 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012589 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12590 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012591 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012592 .build()))
12593 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012594 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12595 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012596 mWindow->assertNoEvents();
12597 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012598 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080012599
12600 // nothing to the window.
12601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012602 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012603 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
12604 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012605 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012606 .build()))
12607 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012608 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012609 mWindow->assertNoEvents();
12610 mSecondWindow->assertNoEvents();
12611}
12612
Arthur Hung54745652022-04-20 07:17:41 +000012613TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012614 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080012615
12616 // Set second window invisible.
12617 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012618 mDispatcher->onWindowInfosChanged(
12619 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080012620
12621 // Move on window.
12622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012623 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012624 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012626 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12627 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012628 mWindow->consumeDragEvent(false, 50, 50);
12629 mSecondWindow->assertNoEvents();
12630
12631 // Move to another window.
12632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012633 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012634 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012636 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12637 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012638 mWindow->consumeDragEvent(true, 150, 50);
12639 mSecondWindow->assertNoEvents();
12640
12641 // drop to another window.
12642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012643 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080012644 {150, 50}))
12645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012646 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012647 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012648 mWindow->assertNoEvents();
12649 mSecondWindow->assertNoEvents();
12650}
12651
Arthur Hung54745652022-04-20 07:17:41 +000012652TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012653 // Ensure window could track pointerIds if it didn't support split touch.
12654 mWindow->setPreventSplitting(true);
12655
Arthur Hung54745652022-04-20 07:17:41 +000012656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012657 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12658 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012659 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012660 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012661
12662 const MotionEvent secondFingerDownEvent =
12663 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012664 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012665 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012666 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12667 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012668 .build();
12669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012670 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012671 InputEventInjectionSync::WAIT_FOR_RESULT))
12672 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012673 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000012674
12675 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012676 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012677}
12678
12679TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12680 // First down on second window.
12681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012682 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12683 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12685
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012686 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012687
12688 // Second down on first window.
12689 const MotionEvent secondFingerDownEvent =
12690 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012691 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012692 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012693 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12694 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012695 .build();
12696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012697 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012698 InputEventInjectionSync::WAIT_FOR_RESULT))
12699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012700 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12701 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012702
12703 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012704 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012705
12706 // Move on window.
12707 const MotionEvent secondFingerMoveEvent =
12708 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12709 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012710 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12711 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012712 .build();
12713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012714 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012715 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012716 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12717 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012718 mWindow->consumeDragEvent(false, 50, 50);
12719 mSecondWindow->consumeMotionMove();
12720
12721 // Release the drag pointer should perform drop.
12722 const MotionEvent secondFingerUpEvent =
12723 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12724 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012725 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12726 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012727 .build();
12728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012729 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012730 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012731 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012732 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012733 mWindow->assertNoEvents();
12734 mSecondWindow->consumeMotionMove();
12735}
12736
Arthur Hung3915c1f2022-05-31 07:17:17 +000012737TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012738 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012739
12740 // Update window of second display.
12741 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012742 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012743 mDispatcher->onWindowInfosChanged(
12744 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12745 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12746 {},
12747 0,
12748 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012749
12750 // Let second display has a touch state.
12751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012752 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012753 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12754 AINPUT_SOURCE_TOUCHSCREEN)
12755 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012756 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012757 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012758 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012759 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012760 mDispatcher->onWindowInfosChanged(
12761 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12762 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12763 {},
12764 0,
12765 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012766
12767 // Move on window.
12768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012769 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012770 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012772 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12773 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012774 mWindow->consumeDragEvent(false, 50, 50);
12775 mSecondWindow->assertNoEvents();
12776
12777 // Move to another window.
12778 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012779 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012780 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012781 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012782 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12783 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012784 mWindow->consumeDragEvent(true, 150, 50);
12785 mSecondWindow->consumeDragEvent(false, 50, 50);
12786
12787 // drop to another window.
12788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012789 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012790 {150, 50}))
12791 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012792 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012793 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012794 mWindow->assertNoEvents();
12795 mSecondWindow->assertNoEvents();
12796}
12797
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012798TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12799 startDrag(true, AINPUT_SOURCE_MOUSE);
12800 // Move on window.
12801 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012802 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012803 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12804 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012805 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012806 .x(50)
12807 .y(50))
12808 .build()))
12809 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012810 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12811 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012812 mWindow->consumeDragEvent(false, 50, 50);
12813 mSecondWindow->assertNoEvents();
12814
12815 // Move to another window.
12816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012817 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012818 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12819 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012820 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012821 .x(150)
12822 .y(50))
12823 .build()))
12824 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012825 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12826 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012827 mWindow->consumeDragEvent(true, 150, 50);
12828 mSecondWindow->consumeDragEvent(false, 50, 50);
12829
12830 // drop to another window.
12831 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012832 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012833 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12834 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012835 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012836 .x(150)
12837 .y(50))
12838 .build()))
12839 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012840 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012841 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012842 mWindow->assertNoEvents();
12843 mSecondWindow->assertNoEvents();
12844}
12845
Linnan Li5af92f92023-07-14 14:36:22 +080012846/**
12847 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12848 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12849 */
12850TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12851 // Down on second window
12852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012853 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12854 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12856
12857 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12858 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12859
12860 // Down on first window
12861 const MotionEvent secondFingerDownEvent =
12862 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012863 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012864 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12865 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12866 .build();
12867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12868 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12869 InputEventInjectionSync::WAIT_FOR_RESULT))
12870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12871 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12872 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12873 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12874
12875 // Start drag on first window
12876 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12877
12878 // Trigger cancel
12879 mDispatcher->cancelCurrentTouch();
12880 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012881 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012882 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012883 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12884
12885 ASSERT_TRUE(mDispatcher->waitForIdle());
12886 // The D&D finished with nullptr
12887 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12888
12889 // Remove drag window
12890 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12891
12892 // Inject a simple gesture, ensure dispatcher not crashed
12893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012894 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12895 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12897 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12898
12899 const MotionEvent moveEvent =
12900 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012901 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012902 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12903 .build();
12904 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12905 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12906 InputEventInjectionSync::WAIT_FOR_RESULT))
12907 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12908 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12909
12910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012911 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012912 {50, 50}))
12913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12914 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12915}
12916
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012917TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12918 // Start hovering over the window.
12919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12920 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012921 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012922
12923 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12924 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12925
12926 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12927 << "Drag and drop should not work with a hovering pointer";
12928}
12929
Linnan Lia512a532024-10-08 16:19:16 +080012930/**
12931 * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if
12932 * we perform a click using Device B, the dispatcher should work well.
12933 */
12934TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) {
12935 const DeviceId deviceA = 1;
12936 const DeviceId deviceB = 2;
12937 // First down on second window with deviceA.
12938 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12939 .deviceId(deviceA)
12940 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12941 .build());
12942 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12943 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12944
12945 // Second down on first window with deviceA
12946 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12947 .deviceId(deviceA)
12948 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12949 .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50))
12950 .build());
12951 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12952 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12953 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12954 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12955
12956 // Perform drag and drop from first window.
12957 ASSERT_TRUE(startDrag(/*sendDown=*/false));
12958
12959 // Click first window with device B, we should ensure dispatcher work well.
12960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
12961 .deviceId(deviceB)
12962 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12963 .build());
12964 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
12965 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12966
12967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
12968 .deviceId(deviceB)
12969 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12970 .build());
12971 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB),
12972 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12973
12974 // Move with device A.
12975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12976 .deviceId(deviceA)
12977 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12978 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12979 .build());
12980
12981 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12982 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12983 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12984 mWindow->consumeDragEvent(false, 51, 51);
12985 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12986 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12987
12988 // Releasing the drag pointer should cause drop.
12989 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12990 .deviceId(deviceA)
12991 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12992 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12993 .build());
12994 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
12995 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12996 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12997 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
12998 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12999 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13000
13001 // Release all pointers.
13002 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13003 .deviceId(deviceA)
13004 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
13005 .build());
13006 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
13007 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
13008 mWindow->assertNoEvents();
13009}
13010
Vishnu Nair062a8672021-09-03 16:07:44 -070013011class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
13012
13013TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
13014 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013015 sp<FakeWindowHandle> window =
13016 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13017 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013018 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013019 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070013020 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013021 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013022 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013023 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070013024
13025 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013026 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013027 window->assertNoEvents();
13028
Prabir Pradhan678438e2023-04-13 19:32:51 +000013029 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013030 AINPUT_SOURCE_TOUCHSCREEN,
13031 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070013032 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013033 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080013034 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070013035 window->assertNoEvents();
13036
13037 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013038 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013039 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013040
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013041 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13042 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013043
Prabir Pradhan678438e2023-04-13 19:32:51 +000013044 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013045 AINPUT_SOURCE_TOUCHSCREEN,
13046 ui::LogicalDisplayId::DEFAULT));
13047 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013048 window->assertNoEvents();
13049}
13050
13051TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
13052 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
13053 std::make_shared<FakeApplicationHandle>();
13054 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013055 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013056 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013057 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013058 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013059 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070013060 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013061 sp<FakeWindowHandle> window =
13062 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13063 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013064 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013065 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013066 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070013067 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013068 mDispatcher->onWindowInfosChanged(
13069 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013070 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013071 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070013072
13073 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013074 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013075 window->assertNoEvents();
13076
Prabir Pradhan678438e2023-04-13 19:32:51 +000013077 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013078 AINPUT_SOURCE_TOUCHSCREEN,
13079 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070013080 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013081 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013082 window->assertNoEvents();
13083
13084 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013085 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013086 mDispatcher->onWindowInfosChanged(
13087 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013088
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013089 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13090 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013091
Prabir Pradhan678438e2023-04-13 19:32:51 +000013092 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013093 AINPUT_SOURCE_TOUCHSCREEN,
13094 ui::LogicalDisplayId::DEFAULT));
13095 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
13096 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070013097 window->assertNoEvents();
13098}
13099
13100TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
13101 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
13102 std::make_shared<FakeApplicationHandle>();
13103 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013104 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013105 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013106 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013107 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013108 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070013109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013110 sp<FakeWindowHandle> window =
13111 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
13112 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013113 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013114 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013115 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070013116 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013117 mDispatcher->onWindowInfosChanged(
13118 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013119 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013120 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070013121
13122 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013123 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013124 window->assertNoEvents();
13125
Prabir Pradhan678438e2023-04-13 19:32:51 +000013126 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013127 AINPUT_SOURCE_TOUCHSCREEN,
13128 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070013129 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013130 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070013131 window->assertNoEvents();
13132
13133 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013134 mDispatcher->onWindowInfosChanged(
13135 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070013136
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013137 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
13138 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013139
Prabir Pradhan678438e2023-04-13 19:32:51 +000013140 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013141 AINPUT_SOURCE_TOUCHSCREEN,
13142 ui::LogicalDisplayId::DEFAULT));
13143 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070013144 window->assertNoEvents();
13145}
13146
Antonio Kantekf16f2832021-09-28 04:39:20 +000013147class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
13148protected:
13149 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000013150 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000013151 sp<FakeWindowHandle> mWindow;
13152 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000013153 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000013154
13155 void SetUp() override {
13156 InputDispatcherTest::SetUp();
13157
13158 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000013159 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013160 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
13161 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013162 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013163 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013164 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
13165 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013166 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000013167 mThirdWindow =
13168 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
13169 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
13170 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013171
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013172 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013173 mDispatcher->onWindowInfosChanged(
13174 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
13175 {},
13176 0,
13177 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000013178 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013179 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013180
Antonio Kantek15beb512022-06-13 22:35:41 +000013181 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013182 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013183 WINDOW_UID, /*hasPermission=*/true,
13184 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070013185 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
13186 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000013187 mThirdWindow->assertNoEvents();
13188 }
13189
13190 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
13191 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000013192 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000013193 SECOND_DISPLAY_ID)) {
13194 mWindow->assertNoEvents();
13195 mSecondWindow->assertNoEvents();
13196 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070013197 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000013198 }
13199
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013200 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000013201 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070013202 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013203 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000013204 mWindow->consumeTouchModeEvent(inTouchMode);
13205 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000013206 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000013207 }
13208};
13209
Antonio Kantek26defcf2022-02-08 01:12:27 +000013210TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080013211 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000013212 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
13213 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000013214 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013215}
13216
Antonio Kantek26defcf2022-02-08 01:12:27 +000013217TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
13218 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013219 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013220 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013221 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013222 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000013223 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013224 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000013225 mWindow->assertNoEvents();
13226 mSecondWindow->assertNoEvents();
13227}
13228
13229TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
13230 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013231 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013232 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013233 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000013234 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000013235 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013236}
13237
Antonio Kantekf16f2832021-09-28 04:39:20 +000013238TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080013239 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000013240 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
13241 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013242 /*hasPermission=*/true,
13243 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000013244 mWindow->assertNoEvents();
13245 mSecondWindow->assertNoEvents();
13246}
13247
Antonio Kantek15beb512022-06-13 22:35:41 +000013248TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
13249 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
13250 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13251 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000013252 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000013253 mWindow->assertNoEvents();
13254 mSecondWindow->assertNoEvents();
13255 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
13256}
13257
Antonio Kantek48710e42022-03-24 14:19:30 -070013258TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
13259 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013261 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070013262 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013263 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070013264
13265 // Then remove focus.
13266 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013267 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070013268
13269 // Assert that caller can switch touch mode by owning one of the last interacted window.
13270 const WindowInfo& windowInfo = *mWindow->getInfo();
13271 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13272 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013273 /*hasPermission=*/false,
13274 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070013275}
13276
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013277class InputDispatcherSpyWindowTest : public InputDispatcherTest {
13278public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013279 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013280 std::shared_ptr<FakeApplicationHandle> application =
13281 std::make_shared<FakeApplicationHandle>();
13282 std::string name = "Fake Spy ";
13283 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013284 sp<FakeWindowHandle> spy =
13285 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
13286 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013287 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013288 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013289 return spy;
13290 }
13291
13292 sp<FakeWindowHandle> createForeground() {
13293 std::shared_ptr<FakeApplicationHandle> application =
13294 std::make_shared<FakeApplicationHandle>();
13295 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013296 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013297 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013298 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013299 return window;
13300 }
13301
13302private:
13303 int mSpyCount{0};
13304};
13305
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013306using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013307/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013308 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
13309 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013310TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070013311 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013312 ScopedSilentDeath _silentDeath;
13313
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013314 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013315 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013316 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013317 ".* not a trusted overlay");
13318}
13319
13320/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013321 * Input injection into a display with a spy window but no foreground windows should succeed.
13322 */
13323TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013324 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013325 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013326
13327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013328 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13329 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013330 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013331 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013332}
13333
13334/**
13335 * Verify the order in which different input windows receive events. The touched foreground window
13336 * (if there is one) should always receive the event first. When there are multiple spy windows, the
13337 * spy windows will receive the event according to their Z-order, where the top-most spy window will
13338 * receive events before ones belows it.
13339 *
13340 * Here, we set up a scenario with four windows in the following Z order from the top:
13341 * spy1, spy2, window, spy3.
13342 * We then inject an event and verify that the foreground "window" receives it first, followed by
13343 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
13344 * window.
13345 */
13346TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
13347 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013348 auto spy1 = createSpy();
13349 auto spy2 = createSpy();
13350 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013351 mDispatcher->onWindowInfosChanged(
13352 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013353 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
13354 const size_t numChannels = channels.size();
13355
Michael Wright8e9a8562022-02-09 13:44:29 +000013356 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013357 if (!epollFd.ok()) {
13358 FAIL() << "Failed to create epoll fd";
13359 }
13360
13361 for (size_t i = 0; i < numChannels; i++) {
13362 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
13363 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
13364 FAIL() << "Failed to add fd to epoll";
13365 }
13366 }
13367
13368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013369 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13370 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013371 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13372
13373 std::vector<size_t> eventOrder;
13374 std::vector<struct epoll_event> events(numChannels);
13375 for (;;) {
13376 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
13377 (100ms).count());
13378 if (nFds < 0) {
13379 FAIL() << "Failed to call epoll_wait";
13380 }
13381 if (nFds == 0) {
13382 break; // epoll_wait timed out
13383 }
13384 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070013385 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070013386 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013387 channels[i]->consumeMotionDown();
13388 }
13389 }
13390
13391 // Verify the order in which the events were received.
13392 EXPECT_EQ(3u, eventOrder.size());
13393 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
13394 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
13395 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
13396}
13397
13398/**
13399 * A spy window using the NOT_TOUCHABLE flag does not receive events.
13400 */
13401TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
13402 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013403 auto spy = createSpy();
13404 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013405 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013406
13407 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013408 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13409 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013410 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013411 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013412 spy->assertNoEvents();
13413}
13414
13415/**
13416 * A spy window will only receive gestures that originate within its touchable region. Gestures that
13417 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
13418 * to the window.
13419 */
13420TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
13421 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013422 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013423 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013424 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013425
13426 // Inject an event outside the spy window's touchable region.
13427 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013428 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13429 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013430 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13431 window->consumeMotionDown();
13432 spy->assertNoEvents();
13433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013434 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13435 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013436 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13437 window->consumeMotionUp();
13438 spy->assertNoEvents();
13439
13440 // Inject an event inside the spy window's touchable region.
13441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13443 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13445 window->consumeMotionDown();
13446 spy->consumeMotionDown();
13447}
13448
13449/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013450 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080013451 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013452 */
13453TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
13454 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013455 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013456 auto spy = createSpy();
13457 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013458 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013459 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013460 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013461
13462 // Inject an event outside the spy window's frame and touchable region.
13463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013464 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13465 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13467 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080013468 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013469}
13470
13471/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013472 * Even when a spy window spans over multiple foreground windows, the spy should receive all
13473 * pointers that are down within its bounds.
13474 */
13475TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
13476 auto windowLeft = createForeground();
13477 windowLeft->setFrame({0, 0, 100, 200});
13478 auto windowRight = createForeground();
13479 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013480 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013481 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013482 mDispatcher->onWindowInfosChanged(
13483 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013484
13485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013486 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13487 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13489 windowLeft->consumeMotionDown();
13490 spy->consumeMotionDown();
13491
13492 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013493 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013494 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013495 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13496 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013497 .build();
13498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013499 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013500 InputEventInjectionSync::WAIT_FOR_RESULT))
13501 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13502 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000013503 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013504}
13505
13506/**
13507 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
13508 * the spy should receive the second pointer with ACTION_DOWN.
13509 */
13510TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
13511 auto window = createForeground();
13512 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013513 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013514 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013515 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013516
13517 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013518 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13519 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013520 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13521 window->consumeMotionDown();
13522 spyRight->assertNoEvents();
13523
13524 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013525 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013526 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013527 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13528 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013529 .build();
13530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013531 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013532 InputEventInjectionSync::WAIT_FOR_RESULT))
13533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000013534 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013535 spyRight->consumeMotionDown();
13536}
13537
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013538/**
13539 * The spy window should not be able to affect whether or not touches are split. Only the foreground
13540 * windows should be allowed to control split touch.
13541 */
13542TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013543 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013544 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013545 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013546 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013547
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013548 auto window = createForeground();
13549 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013550
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013551 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013552
13553 // First finger down, no window touched.
13554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013555 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13556 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013557 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013558 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013559 window->assertNoEvents();
13560
13561 // Second finger down on window, the window should receive touch down.
13562 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013563 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013564 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013565 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013566 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13567 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013568 .build();
13569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013570 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013571 InputEventInjectionSync::WAIT_FOR_RESULT))
13572 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13573
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013574 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000013575 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013576}
13577
13578/**
13579 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
13580 * do not receive key events.
13581 */
13582TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013583 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013584 spy->setFocusable(false);
13585
13586 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013587 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013588 setFocusedWindow(window);
13589 window->consumeFocusEvent(true);
13590
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013591 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013592 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013593 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013594
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013596 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013597 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013598
13599 spy->assertNoEvents();
13600}
13601
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013602using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
13603
13604/**
13605 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
13606 * are currently sent to any other windows - including other spy windows - will also be cancelled.
13607 */
13608TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
13609 auto window = createForeground();
13610 auto spy1 = createSpy();
13611 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013612 mDispatcher->onWindowInfosChanged(
13613 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013614
13615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013616 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13617 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013618 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13619 window->consumeMotionDown();
13620 spy1->consumeMotionDown();
13621 spy2->consumeMotionDown();
13622
13623 // Pilfer pointers from the second spy window.
13624 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
13625 spy2->assertNoEvents();
13626 spy1->consumeMotionCancel();
13627 window->consumeMotionCancel();
13628
13629 // The rest of the gesture should only be sent to the second spy window.
13630 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013631 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013632 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013633 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13634 spy2->consumeMotionMove();
13635 spy1->assertNoEvents();
13636 window->assertNoEvents();
13637}
13638
13639/**
13640 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
13641 * in the middle of the gesture.
13642 */
13643TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13644 auto window = createForeground();
13645 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013646 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013647
13648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013649 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13650 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013651 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013652 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13653 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013654
13655 window->releaseChannel();
13656
13657 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13658
13659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013660 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13661 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013663 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013664}
13665
13666/**
13667 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13668 * the spy, but not to any other windows.
13669 */
13670TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13671 auto spy = createSpy();
13672 auto window = createForeground();
13673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013674 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013675
13676 // First finger down on the window and the spy.
13677 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013678 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13679 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13681 spy->consumeMotionDown();
13682 window->consumeMotionDown();
13683
13684 // Spy window pilfers the pointers.
13685 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13686 window->consumeMotionCancel();
13687
13688 // Second finger down on the window and spy, but the window should not receive the pointer down.
13689 const MotionEvent secondFingerDownEvent =
13690 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013691 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013692 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013693 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13694 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013695 .build();
13696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013697 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013698 InputEventInjectionSync::WAIT_FOR_RESULT))
13699 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13700
Harry Cutts33476232023-01-30 19:57:29 +000013701 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013702
13703 // Third finger goes down outside all windows, so injection should fail.
13704 const MotionEvent thirdFingerDownEvent =
13705 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013706 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013707 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013708 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13709 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13710 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013711 .build();
13712 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013713 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013714 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080013715 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013716
13717 spy->assertNoEvents();
13718 window->assertNoEvents();
13719}
13720
13721/**
13722 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13723 */
13724TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13725 auto spy = createSpy();
13726 spy->setFrame(Rect(0, 0, 100, 100));
13727 auto window = createForeground();
13728 window->setFrame(Rect(0, 0, 200, 200));
13729
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013730 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013731
13732 // First finger down on the window only
13733 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013734 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13735 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013736 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13737 window->consumeMotionDown();
13738
13739 // Second finger down on the spy and window
13740 const MotionEvent secondFingerDownEvent =
13741 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013742 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013743 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013744 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13745 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013746 .build();
13747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013748 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013749 InputEventInjectionSync::WAIT_FOR_RESULT))
13750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13751 spy->consumeMotionDown();
13752 window->consumeMotionPointerDown(1);
13753
13754 // Third finger down on the spy and window
13755 const MotionEvent thirdFingerDownEvent =
13756 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013757 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013758 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013759 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13760 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13761 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013762 .build();
13763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013764 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013765 InputEventInjectionSync::WAIT_FOR_RESULT))
13766 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13767 spy->consumeMotionPointerDown(1);
13768 window->consumeMotionPointerDown(2);
13769
13770 // Spy window pilfers the pointers.
13771 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013772 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13773 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13774 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13775 WithPointerCount(3)));
13776 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13777 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13778 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13779 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013780
13781 spy->assertNoEvents();
13782 window->assertNoEvents();
13783}
13784
13785/**
13786 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13787 * other windows should be canceled. If this results in the cancellation of all pointers for some
13788 * window, then that window should receive ACTION_CANCEL.
13789 */
13790TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13791 auto spy = createSpy();
13792 spy->setFrame(Rect(0, 0, 100, 100));
13793 auto window = createForeground();
13794 window->setFrame(Rect(0, 0, 200, 200));
13795
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013796 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013797
13798 // First finger down on both spy and window
13799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013800 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13801 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13803 window->consumeMotionDown();
13804 spy->consumeMotionDown();
13805
13806 // Second finger down on the spy and window
13807 const MotionEvent secondFingerDownEvent =
13808 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013809 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013810 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013811 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13812 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013813 .build();
13814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013815 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013816 InputEventInjectionSync::WAIT_FOR_RESULT))
13817 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13818 spy->consumeMotionPointerDown(1);
13819 window->consumeMotionPointerDown(1);
13820
13821 // Spy window pilfers the pointers.
13822 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13823 window->consumeMotionCancel();
13824
13825 spy->assertNoEvents();
13826 window->assertNoEvents();
13827}
13828
13829/**
13830 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13831 * be sent to other windows
13832 */
13833TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13834 auto spy = createSpy();
13835 spy->setFrame(Rect(0, 0, 100, 100));
13836 auto window = createForeground();
13837 window->setFrame(Rect(0, 0, 200, 200));
13838
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013839 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013840
13841 // First finger down on both window and spy
13842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013843 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13844 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13846 window->consumeMotionDown();
13847 spy->consumeMotionDown();
13848
13849 // Spy window pilfers the pointers.
13850 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13851 window->consumeMotionCancel();
13852
13853 // Second finger down on the window only
13854 const MotionEvent secondFingerDownEvent =
13855 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013856 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013857 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013858 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13859 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013860 .build();
13861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013862 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013863 InputEventInjectionSync::WAIT_FOR_RESULT))
13864 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13865 window->consumeMotionDown();
13866 window->assertNoEvents();
13867
13868 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13869 spy->consumeMotionMove();
13870 spy->assertNoEvents();
13871}
13872
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013873/**
13874 * A window on the left and a window on the right. Also, a spy window that's above all of the
13875 * windows, and spanning both left and right windows.
13876 * Send simultaneous motion streams from two different devices, one to the left window, and another
13877 * to the right window.
13878 * Pilfer from spy window.
13879 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13880 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013881TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13882 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013883 sp<FakeWindowHandle> spy = createSpy();
13884 spy->setFrame(Rect(0, 0, 200, 200));
13885 sp<FakeWindowHandle> leftWindow = createForeground();
13886 leftWindow->setFrame(Rect(0, 0, 100, 100));
13887
13888 sp<FakeWindowHandle> rightWindow = createForeground();
13889 rightWindow->setFrame(Rect(100, 0, 200, 100));
13890
13891 constexpr int32_t stylusDeviceId = 1;
13892 constexpr int32_t touchDeviceId = 2;
13893
13894 mDispatcher->onWindowInfosChanged(
13895 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13896
13897 // Stylus down on left window and spy
13898 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13899 .deviceId(stylusDeviceId)
13900 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13901 .build());
13902 leftWindow->consumeMotionEvent(
13903 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13904 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13905
13906 // Finger down on right window and spy - but spy already has stylus
13907 mDispatcher->notifyMotion(
13908 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13909 .deviceId(touchDeviceId)
13910 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13911 .build());
13912 rightWindow->consumeMotionEvent(
13913 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013914 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013915
13916 // Act: pilfer from spy. Spy is currently receiving touch events.
13917 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013918 leftWindow->consumeMotionEvent(
13919 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013920 rightWindow->consumeMotionEvent(
13921 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13922
13923 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13924 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13925 .deviceId(stylusDeviceId)
13926 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13927 .build());
13928 mDispatcher->notifyMotion(
13929 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13930 .deviceId(touchDeviceId)
13931 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13932 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013933 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013934
13935 spy->assertNoEvents();
13936 leftWindow->assertNoEvents();
13937 rightWindow->assertNoEvents();
13938}
13939
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013940/**
13941 * A window on the left and a window on the right. Also, a spy window that's above all of the
13942 * windows, and spanning both left and right windows.
13943 * Send simultaneous motion streams from two different devices, one to the left window, and another
13944 * to the right window.
13945 * Pilfer from spy window.
13946 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13947 * The spy should receive both the touch and the stylus events after pilfer.
13948 */
13949TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13950 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13951 sp<FakeWindowHandle> spy = createSpy();
13952 spy->setFrame(Rect(0, 0, 200, 200));
13953 sp<FakeWindowHandle> leftWindow = createForeground();
13954 leftWindow->setFrame(Rect(0, 0, 100, 100));
13955
13956 sp<FakeWindowHandle> rightWindow = createForeground();
13957 rightWindow->setFrame(Rect(100, 0, 200, 100));
13958
13959 constexpr int32_t stylusDeviceId = 1;
13960 constexpr int32_t touchDeviceId = 2;
13961
13962 mDispatcher->onWindowInfosChanged(
13963 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13964
13965 // Stylus down on left window and spy
13966 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13967 .deviceId(stylusDeviceId)
13968 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13969 .build());
13970 leftWindow->consumeMotionEvent(
13971 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13972 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13973
13974 // Finger down on right window and spy
13975 mDispatcher->notifyMotion(
13976 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13977 .deviceId(touchDeviceId)
13978 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13979 .build());
13980 rightWindow->consumeMotionEvent(
13981 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13982 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13983
13984 // Act: pilfer from spy. Spy is currently receiving touch events.
13985 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13986 leftWindow->consumeMotionEvent(
13987 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13988 rightWindow->consumeMotionEvent(
13989 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13990
13991 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013992 // Instead of sending the two MOVE events for each input device together, and then receiving
13993 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13994 // means that the two MOVE events will be initially put into a batch. Once the events are
13995 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13996 // on the implementation of InputConsumer), which would mean that the order of the received
13997 // events could be different depending on whether there are 1 or 2 events pending in the
13998 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13999 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014000 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
14001 .deviceId(stylusDeviceId)
14002 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
14003 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070014004 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014005 mDispatcher->notifyMotion(
14006 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14007 .deviceId(touchDeviceId)
14008 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
14009 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070014010 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014011
14012 spy->assertNoEvents();
14013 leftWindow->assertNoEvents();
14014 rightWindow->assertNoEvents();
14015}
14016
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000014017TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
14018 auto window = createForeground();
14019 auto spy = createSpy();
14020 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
14021
14022 mDispatcher->notifyMotion(
14023 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
14024 .deviceId(1)
14025 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
14026 .build());
14027 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14028 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14029
14030 // Pilfer pointers from the spy window should fail.
14031 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
14032 spy->assertNoEvents();
14033 window->assertNoEvents();
14034}
14035
Prabir Pradhand65552b2021-10-07 11:23:50 -070014036class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
14037public:
14038 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
14039 std::shared_ptr<FakeApplicationHandle> overlayApplication =
14040 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014041 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
14042 "Stylus interceptor window",
14043 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014044 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014045 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080014046 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080014047 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014048 overlay->setTrustedOverlay(true);
14049
14050 std::shared_ptr<FakeApplicationHandle> application =
14051 std::make_shared<FakeApplicationHandle>();
14052 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070014053 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014054 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014055 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014056 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014057
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014058 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014059 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014060 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000014061 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014062 return {std::move(overlay), std::move(window)};
14063 }
14064
14065 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000014066 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070014067 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014068 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070014069 }
14070
14071 void sendStylusEvent(int32_t action) {
14072 NotifyMotionArgs motionArgs =
14073 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014074 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070014075 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000014076 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070014077 }
14078};
14079
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080014080using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
14081
14082TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070014083 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080014084 ScopedSilentDeath _silentDeath;
14085
Prabir Pradhand65552b2021-10-07 11:23:50 -070014086 auto [overlay, window] = setupStylusOverlayScenario();
14087 overlay->setTrustedOverlay(false);
14088 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014089 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
14090 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070014091 ".* not a trusted overlay");
14092}
14093
14094TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
14095 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014096 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014097
14098 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14099 overlay->consumeMotionDown();
14100 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14101 overlay->consumeMotionUp();
14102
14103 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
14104 window->consumeMotionDown();
14105 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
14106 window->consumeMotionUp();
14107
14108 overlay->assertNoEvents();
14109 window->assertNoEvents();
14110}
14111
14112TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
14113 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080014114 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014115 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070014116
14117 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14118 overlay->consumeMotionDown();
14119 window->consumeMotionDown();
14120 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14121 overlay->consumeMotionUp();
14122 window->consumeMotionUp();
14123
14124 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
14125 window->consumeMotionDown();
14126 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
14127 window->consumeMotionUp();
14128
14129 overlay->assertNoEvents();
14130 window->assertNoEvents();
14131}
14132
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000014133/**
14134 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
14135 * The scenario is as follows:
14136 * - The stylus interceptor overlay is configured as a spy window.
14137 * - The stylus interceptor spy receives the start of a new stylus gesture.
14138 * - It pilfers pointers and then configures itself to no longer be a spy.
14139 * - The stylus interceptor continues to receive the rest of the gesture.
14140 */
14141TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
14142 auto [overlay, window] = setupStylusOverlayScenario();
14143 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014144 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000014145
14146 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
14147 overlay->consumeMotionDown();
14148 window->consumeMotionDown();
14149
14150 // The interceptor pilfers the pointers.
14151 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
14152 window->consumeMotionCancel();
14153
14154 // The interceptor configures itself so that it is no longer a spy.
14155 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014156 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000014157
14158 // It continues to receive the rest of the stylus gesture.
14159 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
14160 overlay->consumeMotionMove();
14161 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
14162 overlay->consumeMotionUp();
14163
14164 window->assertNoEvents();
14165}
14166
Prabir Pradhan5735a322022-04-11 17:23:34 +000014167struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014168 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000014169 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000014170 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
14171 std::unique_ptr<InputDispatcher>& mDispatcher;
14172
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014173 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000014174 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
14175
14176 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014177 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014178 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000014179 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
14180 AMOTION_EVENT_INVALID_CURSOR_POSITION},
14181 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
14182 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
14183 }
14184
14185 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080014186 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014187 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000014188 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000014189 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000014190 mPolicyFlags);
14191 }
14192
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014193 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000014194 std::shared_ptr<FakeApplicationHandle> overlayApplication =
14195 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014196 sp<FakeWindowHandle> window =
14197 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
14198 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014199 window->setOwnerInfo(mPid, mUid);
14200 return window;
14201 }
14202};
14203
14204using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
14205
14206TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014207 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014208 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014209 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014210
14211 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14212 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14213 window->consumeMotionDown();
14214
14215 setFocusedWindow(window);
14216 window->consumeFocusEvent(true);
14217
14218 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14219 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014220 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014221}
14222
14223TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014224 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014225 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014226 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014227
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014228 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014229 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14230 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14231
14232 setFocusedWindow(window);
14233 window->consumeFocusEvent(true);
14234
14235 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14236 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
14237 window->assertNoEvents();
14238}
14239
14240TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014241 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014242 auto window = owner.createWindow("Owned window");
14243 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014244 spy->setSpy(true);
14245 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014246 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014247
14248 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14249 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14250 spy->consumeMotionDown();
14251 window->consumeMotionDown();
14252}
14253
14254TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014255 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014256 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014257
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014258 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014259 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014260 randosSpy->setSpy(true);
14261 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014262 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014263
14264 // The event is targeted at owner's window, so injection should succeed, but the spy should
14265 // not receive the event.
14266 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14267 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14268 randosSpy->assertNoEvents();
14269 window->consumeMotionDown();
14270}
14271
14272TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014273 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014274 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014275
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014276 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014277 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014278 randosSpy->setSpy(true);
14279 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014280 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014281
14282 // A user that has injection permission can inject into any window.
14283 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014284 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014285 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000014286 randosSpy->consumeMotionDown();
14287 window->consumeMotionDown();
14288
14289 setFocusedWindow(randosSpy);
14290 randosSpy->consumeFocusEvent(true);
14291
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014292 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014293 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014294 window->assertNoEvents();
14295}
14296
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014297TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014298 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014299 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014300
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014301 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014302 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014303 randosWindow->setFrame(Rect{-10, -10, -5, -5});
14304 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014305 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014306
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014307 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000014308 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14309 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14310 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014311 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000014312}
14313
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014314using InputDispatcherPointerInWindowTest = InputDispatcherTest;
14315
14316TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
14317 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14318
14319 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014320 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014321 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014322 sp<FakeWindowHandle> right =
14323 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14324 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014325 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014326 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14327 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014328 spy->setFrame(Rect(0, 0, 200, 100));
14329 spy->setTrustedOverlay(true);
14330 spy->setSpy(true);
14331
14332 mDispatcher->onWindowInfosChanged(
14333 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14334
14335 // Hover into the left window.
14336 mDispatcher->notifyMotion(
14337 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
14338 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
14339 .build());
14340
14341 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14342 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14343
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014344 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14345 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014346 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014347 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14348 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014349 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014350 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14351 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014352 /*pointerId=*/0));
14353
14354 // Hover move to the right window.
14355 mDispatcher->notifyMotion(
14356 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14357 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14358 .build());
14359
14360 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14361 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14362 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
14363
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014364 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14365 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014366 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014367 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14368 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014369 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014370 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14371 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014372 /*pointerId=*/0));
14373
14374 // Stop hovering.
14375 mDispatcher->notifyMotion(
14376 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
14377 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14378 .build());
14379
14380 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14381 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14382
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014383 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14384 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014385 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014386 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14387 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014388 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014389 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14390 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014391 /*pointerId=*/0));
14392}
14393
14394TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
14395 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14396
14397 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014398 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014399 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014400 sp<FakeWindowHandle> right =
14401 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14402 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014403 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014404 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14405 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014406 spy->setFrame(Rect(0, 0, 200, 100));
14407 spy->setTrustedOverlay(true);
14408 spy->setSpy(true);
14409
14410 mDispatcher->onWindowInfosChanged(
14411 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14412
14413 // First pointer down on left window.
14414 mDispatcher->notifyMotion(
14415 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14416 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14417 .build());
14418
14419 left->consumeMotionDown();
14420 spy->consumeMotionDown();
14421
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014422 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14423 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014424 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014425 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14426 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014427 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014428 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14429 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014430 /*pointerId=*/0));
14431
14432 // Second pointer down on right window.
14433 mDispatcher->notifyMotion(
14434 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14435 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14436 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14437 .build());
14438
14439 left->consumeMotionMove();
14440 right->consumeMotionDown();
14441 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
14442
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014443 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14444 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014445 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014446 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14447 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014448 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014449 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14450 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014451 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014452 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14453 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014454 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014455 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14456 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014457 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014458 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14459 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014460 /*pointerId=*/1));
14461
14462 // Second pointer up.
14463 mDispatcher->notifyMotion(
14464 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
14465 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14466 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14467 .build());
14468
14469 left->consumeMotionMove();
14470 right->consumeMotionUp();
14471 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
14472
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014473 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14474 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014475 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014476 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14477 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014478 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014479 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14480 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014481 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014482 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14483 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014484 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014485 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14486 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014487 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014488 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14489 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014490 /*pointerId=*/1));
14491
14492 // First pointer up.
14493 mDispatcher->notifyMotion(
14494 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14495 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14496 .build());
14497
14498 left->consumeMotionUp();
14499 spy->consumeMotionUp();
14500
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014501 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14502 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014503 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014504 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14505 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014506 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014507 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14508 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014509 /*pointerId=*/0));
14510}
14511
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014512TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
14513 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14515
14516 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014517 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014518 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014519 sp<FakeWindowHandle> right =
14520 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14521 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014522 right->setFrame(Rect(100, 0, 200, 100));
14523
14524 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14525
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014526 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14527 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014528 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014529 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14530 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014531 /*pointerId=*/0));
14532
14533 // Hover move into the window.
14534 mDispatcher->notifyMotion(
14535 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14536 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14537 .rawXCursorPosition(50)
14538 .rawYCursorPosition(50)
14539 .deviceId(DEVICE_ID)
14540 .build());
14541
14542 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14543
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014544 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14545 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014546 /*pointerId=*/0));
14547
14548 // Move the mouse with another device. This cancels the hovering pointer from the first device.
14549 mDispatcher->notifyMotion(
14550 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14551 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14552 .rawXCursorPosition(51)
14553 .rawYCursorPosition(50)
14554 .deviceId(SECOND_DEVICE_ID)
14555 .build());
14556
14557 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14558 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14559
14560 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14561 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014562 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14563 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014564 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014565 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014566 SECOND_DEVICE_ID,
14567 /*pointerId=*/0));
14568
14569 // Move the mouse outside the window. Document the current behavior, where the window does not
14570 // receive HOVER_EXIT even though the mouse left the window.
14571 mDispatcher->notifyMotion(
14572 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14573 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14574 .rawXCursorPosition(150)
14575 .rawYCursorPosition(50)
14576 .deviceId(SECOND_DEVICE_ID)
14577 .build());
14578
14579 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14580 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014581 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14582 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014583 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014584 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014585 SECOND_DEVICE_ID,
14586 /*pointerId=*/0));
14587}
14588
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014589/**
14590 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
14591 * the same cursor, and therefore have a shared motion event stream.
14592 */
14593TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
14594 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
14595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14596
14597 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014598 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014599 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014600 sp<FakeWindowHandle> right =
14601 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14602 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014603 right->setFrame(Rect(100, 0, 200, 100));
14604
14605 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14606
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014607 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14608 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014609 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014610 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14611 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014612 /*pointerId=*/0));
14613
14614 // Hover move into the window.
14615 mDispatcher->notifyMotion(
14616 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14617 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14618 .rawXCursorPosition(50)
14619 .rawYCursorPosition(50)
14620 .deviceId(DEVICE_ID)
14621 .build());
14622
14623 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14624
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014625 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14626 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014627 /*pointerId=*/0));
14628
14629 // Move the mouse with another device
14630 mDispatcher->notifyMotion(
14631 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14632 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14633 .rawXCursorPosition(51)
14634 .rawYCursorPosition(50)
14635 .deviceId(SECOND_DEVICE_ID)
14636 .build());
14637 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14638
14639 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14640 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014641 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14642 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014643 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014644 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014645 SECOND_DEVICE_ID,
14646 /*pointerId=*/0));
14647
14648 // Move the mouse outside the window. Document the current behavior, where the window does not
14649 // receive HOVER_EXIT even though the mouse left the window.
14650 mDispatcher->notifyMotion(
14651 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14652 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14653 .rawXCursorPosition(150)
14654 .rawYCursorPosition(50)
14655 .deviceId(SECOND_DEVICE_ID)
14656 .build());
14657
14658 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014659 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14660 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014661 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014662 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014663 SECOND_DEVICE_ID,
14664 /*pointerId=*/0));
14665}
14666
Arpit Singhb65e2bd2024-06-03 09:48:16 +000014667TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14668 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14669 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14670}
14671
Garfield Tane84e6f92019-08-29 17:28:41 -070014672} // namespace android::inputdispatcher