blob: d77bf3d1ee7dc7509db773248eba03058393d948 [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 Pradhane3b28dd2023-10-06 04:19:29 +000021#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080022
Cody Heiner166a5af2023-07-07 12:25:00 -070023#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000024#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070025#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080026#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080027#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070028#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070029#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000030#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000031#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000032#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080033#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080034#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080035#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100036#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070037#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070038#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080039#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080040#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100041
Garfield Tan1c7bc862020-01-28 13:24:04 -080042#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080043#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070044#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080045#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080046#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080047
Garfield Tan1c7bc862020-01-28 13:24:04 -080048using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050049using android::gui::FocusRequest;
50using android::gui::TouchOcclusionMode;
51using android::gui::WindowInfo;
52using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080053using android::os::InputEventInjectionResult;
54using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080055
Garfield Tane84e6f92019-08-29 17:28:41 -070056namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080057
Dominik Laskowski2f01d772022-03-23 16:01:29 -070058using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080059using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000060using testing::Not;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070061
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070062namespace {
63
Michael Wrightd02c5b62014-02-10 15:10:22 -080064// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000065static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080066
67// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000068static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080069static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080070
Jeff Brownf086ddb2014-02-11 14:28:48 -080071// An arbitrary display id.
Arthur Hungabbb9d82021-09-01 14:52:30 +000072static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
73static constexpr int32_t SECOND_DISPLAY_ID = 1;
Jeff Brownf086ddb2014-02-11 14:28:48 -080074
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000075// Ensure common actions are interchangeable between keys and motions for convenience.
76static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
77static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080078static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
79static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
80static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
81static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070082static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080083static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070084static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080085static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080086static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080087/**
88 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
89 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
90 * index 0) is the new pointer going down. The same pointer could have been placed at a different
91 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
92 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
93 * pointer id=0 leaves but the pointer id=1 remains.
94 */
95static constexpr int32_t POINTER_0_DOWN =
96 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080097static constexpr int32_t POINTER_1_DOWN =
98 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +000099static constexpr int32_t POINTER_2_DOWN =
100 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000101static constexpr int32_t POINTER_3_DOWN =
102 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000103static constexpr int32_t POINTER_0_UP =
104 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800105static constexpr int32_t POINTER_1_UP =
106 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000107static constexpr int32_t POINTER_2_UP =
108 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800109
Antonio Kantek15beb512022-06-13 22:35:41 +0000110// The default pid and uid for windows created on the primary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000111static constexpr gui::Pid WINDOW_PID{999};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000112static constexpr gui::Uid WINDOW_UID{1001};
Prabir Pradhan5735a322022-04-11 17:23:34 +0000113
Antonio Kantek15beb512022-06-13 22:35:41 +0000114// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000115static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000116static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000117
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000118// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000119static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000120
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700121/**
122 * If we expect to receive the event, the timeout can be made very long. When the test are running
123 * correctly, we will actually never wait until the end of the timeout because the wait will end
124 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
125 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
126 * developer can see the failure quickly (on human scale).
127 */
128static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
129/**
130 * When no event is expected, we can have a very short timeout. A large value here would slow down
131 * the tests. In the unlikely event of system being too slow, the event may still be present but the
132 * timeout would complete before it is consumed. This would result in test flakiness. If this
133 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
134 * would get noticed and addressed quickly.
135 */
136static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
137
Arthur Hungc539dbb2022-12-08 07:45:36 +0000138static constexpr int expectedWallpaperFlags =
139 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
140
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800141using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
142
Gang Wang342c9272020-01-13 13:15:04 -0500143/**
144 * Return a DOWN key event with KEYCODE_A.
145 */
146static KeyEvent getTestKeyEvent() {
147 KeyEvent event;
148
Garfield Tanfbe732e2020-01-24 11:26:14 -0800149 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
150 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
151 ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500152 return event;
153}
154
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700155} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800156
Michael Wrightd02c5b62014-02-10 15:10:22 -0800157// --- InputDispatcherTest ---
158
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000159// The trace is a global variable for now, to avoid having to pass it into all of the
160// FakeWindowHandles created throughout the tests.
161// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
162static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
163
Michael Wrightd02c5b62014-02-10 15:10:22 -0800164class InputDispatcherTest : public testing::Test {
165protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000166 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700167 std::unique_ptr<InputDispatcher> mDispatcher;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800168
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000169 void SetUp() override {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000170 gVerifyingTrace->reset();
Prabir Pradhana41d2442023-04-20 21:30:40 +0000171 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000172 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
173 std::make_unique<FakeInputTracingBackend>(
174 gVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700175
Harry Cutts101ee9b2023-07-06 18:04:14 +0000176 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000177 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700178 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800179 }
180
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 void TearDown() override {
Prabir Pradhan0eaf1402024-02-05 22:43:04 +0000182 ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700183 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000184 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700185 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800186 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700187
188 /**
189 * Used for debugging when writing the test
190 */
191 void dumpDispatcherState() {
192 std::string dump;
193 mDispatcher->dump(dump);
194 std::stringstream ss(dump);
195 std::string to;
196
197 while (std::getline(ss, to, '\n')) {
198 ALOGE("%s", to.c_str());
199 }
200 }
Vishnu Nair958da932020-08-21 17:12:37 -0700201
Chavi Weingarten847e8512023-03-29 00:26:09 +0000202 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700203 FocusRequest request;
204 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000205 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700206 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
207 request.displayId = window->getInfo()->displayId;
208 mDispatcher->setFocusedWindow(request);
209 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800210};
211
Michael Wrightd02c5b62014-02-10 15:10:22 -0800212TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
213 KeyEvent event;
214
215 // Rejects undefined key actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800216 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
217 INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000218 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600219 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800220 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000221 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000222 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800223 << "Should reject key events with undefined action.";
224
225 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800226 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
227 INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600228 ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800229 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000230 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000231 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800232 << "Should reject key events with ACTION_MULTIPLE.";
233}
234
235TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
236 MotionEvent event;
237 PointerProperties pointerProperties[MAX_POINTERS + 1];
238 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800239 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240 pointerProperties[i].clear();
241 pointerProperties[i].id = i;
242 pointerCoords[i].clear();
243 }
244
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800245 // Some constants commonly used below
246 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
247 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
248 constexpr int32_t metaState = AMETA_NONE;
249 constexpr MotionClassification classification = MotionClassification::NONE;
250
chaviw9eaa22c2020-07-01 16:21:27 -0700251 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800252 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800253 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000254 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700255 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700256 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
257 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000258 /*pointerCount=*/1, pointerProperties, pointerCoords);
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 motion events with undefined action.";
263
264 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800265 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800266 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
267 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
268 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
269 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000270 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800271 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000272 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000273 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800274 << "Should reject motion events with pointer down index too large.";
275
Garfield Tanfbe732e2020-01-24 11:26:14 -0800276 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700277 AMOTION_EVENT_ACTION_POINTER_DOWN |
278 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700279 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
280 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700281 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000282 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800283 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000284 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000285 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800286 << "Should reject motion events with pointer down index too small.";
287
288 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800289 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800290 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
291 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
292 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
293 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000294 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800295 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000296 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000297 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800298 << "Should reject motion events with pointer up index too large.";
299
Garfield Tanfbe732e2020-01-24 11:26:14 -0800300 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700301 AMOTION_EVENT_ACTION_POINTER_UP |
302 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700303 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
304 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700305 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000306 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800307 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000308 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000309 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800310 << "Should reject motion events with pointer up index too small.";
311
312 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800313 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
314 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700315 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700316 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
317 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000318 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800319 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000320 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000321 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800322 << "Should reject motion events with 0 pointers.";
323
Garfield Tanfbe732e2020-01-24 11:26:14 -0800324 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
325 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700326 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700327 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
328 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000329 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800330 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000331 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000332 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800333 << "Should reject motion events with more than MAX_POINTERS pointers.";
334
335 // Rejects motion events with invalid pointer ids.
336 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800337 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
338 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700339 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700340 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
341 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000342 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800343 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000344 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000345 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800346 << "Should reject motion events with pointer ids less than 0.";
347
348 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800349 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
350 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700351 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700352 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
353 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000354 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800355 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000356 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000357 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800358 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
359
360 // Rejects motion events with duplicate pointer ids.
361 pointerProperties[0].id = 1;
362 pointerProperties[1].id = 1;
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=*/2, 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 duplicate pointer ids.";
373}
374
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800375/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
376
377TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
378 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000379 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800380 ASSERT_TRUE(mDispatcher->waitForIdle());
381
382 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
383}
384
385TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000386 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
387 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000388 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000389 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800390
391 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
392 args.policyFlags |= POLICY_FLAG_TRUSTED;
393 mFakePolicy->assertNotifySwitchWasCalled(args);
394}
395
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700396namespace {
397
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700398static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -0700399// Default input dispatching timeout if there is no focused application or paused window
400// from which to determine an appropriate dispatching timeout.
401static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
402 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
403 android::base::HwTimeoutMultiplier());
Arthur Hungb92218b2018-08-14 12:00:21 +0800404
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800405class FakeInputReceiver {
Arthur Hungb92218b2018-08-14 12:00:21 +0800406public:
Garfield Tan15601662020-09-22 15:32:38 -0700407 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700408 : mConsumer(std::move(clientChannel)), mName(name) {}
chaviwd1c23182019-12-20 18:44:56 -0800409
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800410 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false) {
411 auto [consumeSeq, event] = receiveEvent(timeout);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700412 if (!consumeSeq) {
413 return nullptr;
414 }
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000415 finishEvent(*consumeSeq, handled);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800416 return std::move(event);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700417 }
418
419 /**
420 * Receive an event without acknowledging it.
421 * Return the sequence number that could later be used to send finished signal.
422 */
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800423 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
424 std::chrono::milliseconds timeout) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800425 uint32_t consumeSeq;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800426 std::unique_ptr<InputEvent> event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800427
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800428 std::chrono::time_point start = std::chrono::steady_clock::now();
429 status_t status = WOULD_BLOCK;
430 while (status == WOULD_BLOCK) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800431 InputEvent* rawEventPtr = nullptr;
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700432 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800433 &rawEventPtr);
434 event = std::unique_ptr<InputEvent>(rawEventPtr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800435 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700436 if (elapsed > timeout) {
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800437 break;
438 }
439 }
440
441 if (status == WOULD_BLOCK) {
442 // Just means there's no event available.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800443 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800444 }
445
446 if (status != OK) {
447 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800448 return std::make_pair(std::nullopt, nullptr);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800449 }
450 if (event == nullptr) {
451 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800452 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800453 return std::make_pair(consumeSeq, std::move(event));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700454 }
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800455
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700456 /**
457 * To be used together with "receiveEvent" to complete the consumption of an event.
458 */
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +0000459 void finishEvent(uint32_t consumeSeq, bool handled = true) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700461 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800462 }
463
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000464 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000466 ASSERT_EQ(OK, status);
467 }
468
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700469 void consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000470 std::optional<int32_t> expectedDisplayId,
471 std::optional<int32_t> expectedFlags) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800472 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou08b574f2019-11-15 18:05:52 -0800473
474 ASSERT_NE(nullptr, event) << mName.c_str()
475 << ": consumer should have returned non-NULL event.";
Arthur Hungb92218b2018-08-14 12:00:21 +0800476 ASSERT_EQ(expectedEventType, event->getType())
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700477 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
478 << " event, got " << *event;
Arthur Hungb92218b2018-08-14 12:00:21 +0800479
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000480 if (expectedDisplayId.has_value()) {
481 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
482 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800483
Tiger Huang8664f8c2018-10-11 19:14:35 +0800484 switch (expectedEventType) {
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700485 case InputEventType::KEY: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800486 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700487 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000488 if (expectedFlags.has_value()) {
489 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
490 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800491 break;
492 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700493 case InputEventType::MOTION: {
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800494 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700495 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000496 if (expectedFlags.has_value()) {
497 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
498 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800499 break;
500 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700501 case InputEventType::FOCUS: {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100502 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
503 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700504 case InputEventType::CAPTURE: {
Prabir Pradhan99987712020-11-10 18:43:05 -0800505 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
506 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700507 case InputEventType::TOUCH_MODE: {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000508 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
509 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700510 case InputEventType::DRAG: {
arthurhungb89ccb02020-12-30 16:19:01 +0800511 FAIL() << "Use 'consumeDragEvent' for DRAG events";
512 }
Tiger Huang8664f8c2018-10-11 19:14:35 +0800513 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800514 }
515
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800516 std::unique_ptr<MotionEvent> consumeMotion() {
517 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800518
519 if (event == nullptr) {
520 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
521 return nullptr;
522 }
523
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700524 if (event->getType() != InputEventType::MOTION) {
525 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800526 return nullptr;
527 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800528 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800529 }
530
531 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800532 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800533 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
534 ASSERT_THAT(*motionEvent, matcher);
535 }
536
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100537 void consumeFocusEvent(bool hasFocus, bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800538 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100539 ASSERT_NE(nullptr, event) << mName.c_str()
540 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700541 ASSERT_EQ(InputEventType::FOCUS, event->getType())
542 << "Instead of FocusEvent, got " << *event;
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100543
544 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
545 << mName.c_str() << ": event displayId should always be NONE.";
546
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800547 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
548 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100549 }
550
Prabir Pradhan99987712020-11-10 18:43:05 -0800551 void consumeCaptureEvent(bool hasCapture) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800552 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Prabir Pradhan99987712020-11-10 18:43:05 -0800553 ASSERT_NE(nullptr, event) << mName.c_str()
554 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700555 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
556 << "Instead of CaptureEvent, got " << *event;
Prabir Pradhan99987712020-11-10 18:43:05 -0800557
558 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
559 << mName.c_str() << ": event displayId should always be NONE.";
560
561 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
562 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
563 }
564
arthurhungb89ccb02020-12-30 16:19:01 +0800565 void consumeDragEvent(bool isExiting, float x, float y) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800566 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
arthurhungb89ccb02020-12-30 16:19:01 +0800567 ASSERT_NE(nullptr, event) << mName.c_str()
568 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700569 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
arthurhungb89ccb02020-12-30 16:19:01 +0800570
571 EXPECT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
572 << mName.c_str() << ": event displayId should always be NONE.";
573
574 const auto& dragEvent = static_cast<const DragEvent&>(*event);
575 EXPECT_EQ(isExiting, dragEvent.isExiting());
576 EXPECT_EQ(x, dragEvent.getX());
577 EXPECT_EQ(y, dragEvent.getY());
578 }
579
Antonio Kantekf16f2832021-09-28 04:39:20 +0000580 void consumeTouchModeEvent(bool inTouchMode) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800581 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
Antonio Kantekf16f2832021-09-28 04:39:20 +0000582 ASSERT_NE(nullptr, event) << mName.c_str()
583 << ": consumer should have returned non-NULL event.";
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700584 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
585 << "Instead of TouchModeEvent, got " << *event;
Antonio Kantekf16f2832021-09-28 04:39:20 +0000586
587 ASSERT_EQ(ADISPLAY_ID_NONE, event->getDisplayId())
588 << mName.c_str() << ": event displayId should always be NONE.";
589 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
590 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
591 }
592
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800593 void assertNoEvents(std::chrono::milliseconds timeout) {
594 std::unique_ptr<InputEvent> event = consume(timeout);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700595 if (event == nullptr) {
596 return;
597 }
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700598 if (event->getType() == InputEventType::KEY) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700599 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800600 ADD_FAILURE() << "Received key event " << keyEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700601 } else if (event->getType() == InputEventType::MOTION) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700602 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800603 ADD_FAILURE() << "Received motion event " << motionEvent;
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700604 } else if (event->getType() == InputEventType::FOCUS) {
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700605 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
606 ADD_FAILURE() << "Received focus event, hasFocus = "
607 << (focusEvent.getHasFocus() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700608 } else if (event->getType() == InputEventType::CAPTURE) {
Prabir Pradhan99987712020-11-10 18:43:05 -0800609 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
610 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
611 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
Siarhei Vishniakou63b63612023-04-12 11:00:23 -0700612 } else if (event->getType() == InputEventType::TOUCH_MODE) {
Antonio Kantekf16f2832021-09-28 04:39:20 +0000613 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
614 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
615 << (touchModeEvent.isInTouchMode() ? "true" : "false");
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700616 }
617 FAIL() << mName.c_str()
618 << ": should not have received any events, so consume() should return NULL";
chaviwd1c23182019-12-20 18:44:56 -0800619 }
620
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700621 sp<IBinder> getToken() { return mConsumer.getChannel()->getConnectionToken(); }
chaviwd1c23182019-12-20 18:44:56 -0800622
Siarhei Vishniakou8d660132024-01-11 16:48:44 -0800623 int getChannelFd() { return mConsumer.getChannel()->getFd(); }
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800624
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700625private:
626 InputConsumer mConsumer;
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800627 DynamicInputEventFactory mEventFactory;
chaviwd1c23182019-12-20 18:44:56 -0800628
629 std::string mName;
630};
631
chaviw3277faf2021-05-19 16:45:23 -0500632class FakeWindowHandle : public WindowInfoHandle {
chaviwd1c23182019-12-20 18:44:56 -0800633public:
634 static const int32_t WIDTH = 600;
635 static const int32_t HEIGHT = 800;
chaviwd1c23182019-12-20 18:44:56 -0800636
Chris Yea209fde2020-07-22 13:54:51 -0700637 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700638 const std::unique_ptr<InputDispatcher>& dispatcher, const std::string name,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +0000639 int32_t displayId, bool createInputChannel = true)
chaviwd1c23182019-12-20 18:44:56 -0800640 : mName(name) {
Prabir Pradhane7cc69c2024-01-05 21:35:28 +0000641 sp<IBinder> token;
642 if (createInputChannel) {
Garfield Tan15601662020-09-22 15:32:38 -0700643 base::Result<std::unique_ptr<InputChannel>> channel =
644 dispatcher->createInputChannel(name);
645 token = (*channel)->getConnectionToken();
646 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
chaviwd1c23182019-12-20 18:44:56 -0800647 }
648
649 inputApplicationHandle->updateInfo();
650 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
651
Prabir Pradhane7cc69c2024-01-05 21:35:28 +0000652 mInfo.token = token;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700653 mInfo.id = sId++;
chaviwd1c23182019-12-20 18:44:56 -0800654 mInfo.name = name;
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500655 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000656 mInfo.alpha = 1.0;
Chavi Weingarten7f019192023-08-08 20:39:01 +0000657 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
chaviw1ff3d1e2020-07-01 15:53:47 -0700658 mInfo.transform.set(0, 0);
chaviwd1c23182019-12-20 18:44:56 -0800659 mInfo.globalScaleFactor = 1.0;
660 mInfo.touchableRegion.clear();
661 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
Prabir Pradhan5735a322022-04-11 17:23:34 +0000662 mInfo.ownerPid = WINDOW_PID;
663 mInfo.ownerUid = WINDOW_UID;
chaviwd1c23182019-12-20 18:44:56 -0800664 mInfo.displayId = displayId;
Prabir Pradhan51e7db02022-02-07 06:02:57 -0800665 mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
chaviwd1c23182019-12-20 18:44:56 -0800666 }
667
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -0700668 sp<FakeWindowHandle> clone(int32_t displayId) {
669 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
670 handle->mInfo = mInfo;
671 handle->mInfo.displayId = displayId;
672 handle->mInfo.id = sId++;
673 handle->mInputReceiver = mInputReceiver;
674 return handle;
675 }
676
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800677 void setTouchable(bool touchable) {
678 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, !touchable);
679 }
chaviwd1c23182019-12-20 18:44:56 -0800680
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800681 void setFocusable(bool focusable) {
682 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_FOCUSABLE, !focusable);
683 }
684
685 void setVisible(bool visible) {
686 mInfo.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
687 }
Vishnu Nair958da932020-08-21 17:12:37 -0700688
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700689 void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
Siarhei Vishniakouc1ae5562020-06-30 14:22:57 -0500690 mInfo.dispatchingTimeout = timeout;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700691 }
692
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800693 void setPaused(bool paused) {
694 mInfo.setInputConfig(WindowInfo::InputConfig::PAUSE_DISPATCHING, paused);
695 }
696
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800697 void setPreventSplitting(bool preventSplitting) {
698 mInfo.setInputConfig(WindowInfo::InputConfig::PREVENT_SPLITTING, preventSplitting);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800699 }
700
701 void setSlippery(bool slippery) {
702 mInfo.setInputConfig(WindowInfo::InputConfig::SLIPPERY, slippery);
703 }
704
705 void setWatchOutsideTouch(bool watchOutside) {
706 mInfo.setInputConfig(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
707 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700708
Prabir Pradhan51e7db02022-02-07 06:02:57 -0800709 void setSpy(bool spy) { mInfo.setInputConfig(WindowInfo::InputConfig::SPY, spy); }
710
711 void setInterceptsStylus(bool interceptsStylus) {
712 mInfo.setInputConfig(WindowInfo::InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
713 }
714
715 void setDropInput(bool dropInput) {
716 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT, dropInput);
717 }
718
719 void setDropInputIfObscured(bool dropInputIfObscured) {
720 mInfo.setInputConfig(WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
721 }
722
723 void setNoInputChannel(bool noInputChannel) {
724 mInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, noInputChannel);
725 }
726
Josep del Riob3981622023-04-18 15:49:45 +0000727 void setDisableUserActivity(bool disableUserActivity) {
728 mInfo.setInputConfig(WindowInfo::InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
729 }
730
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -0700731 void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
732 mInfo.setInputConfig(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH,
733 shouldGlobalStylusBlockTouch);
734 }
735
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000736 void setAlpha(float alpha) { mInfo.alpha = alpha; }
737
chaviw3277faf2021-05-19 16:45:23 -0500738 void setTouchOcclusionMode(TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; }
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000739
Bernardo Rufino7393d172021-02-26 13:56:11 +0000740 void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
741
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700742 void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) {
Chavi Weingarten7f019192023-08-08 20:39:01 +0000743 mInfo.frame = frame;
chaviwd1c23182019-12-20 18:44:56 -0800744 mInfo.touchableRegion.clear();
745 mInfo.addTouchableRegion(frame);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700746
747 const Rect logicalDisplayFrame = displayTransform.transform(frame);
748 ui::Transform translate;
749 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
750 mInfo.transform = translate * displayTransform;
chaviwd1c23182019-12-20 18:44:56 -0800751 }
752
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800753 void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
754
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800755 void setIsWallpaper(bool isWallpaper) {
756 mInfo.setInputConfig(WindowInfo::InputConfig::IS_WALLPAPER, isWallpaper);
757 }
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000758
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800759 void setDupTouchToWallpaper(bool hasWallpaper) {
760 mInfo.setInputConfig(WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
761 }
chaviwd1c23182019-12-20 18:44:56 -0800762
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800763 void setTrustedOverlay(bool trustedOverlay) {
764 mInfo.setInputConfig(WindowInfo::InputConfig::TRUSTED_OVERLAY, trustedOverlay);
765 }
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500766
chaviw9eaa22c2020-07-01 16:21:27 -0700767 void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
768 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
769 }
770
771 void setWindowScale(float xScale, float yScale) { setWindowTransform(xScale, 0, 0, yScale); }
chaviwaf87b3e2019-10-01 16:59:28 -0700772
yunho.shinf4a80b82020-11-16 21:13:57 +0900773 void setWindowOffset(float offsetX, float offsetY) { mInfo.transform.set(offsetX, offsetY); }
774
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800775 std::unique_ptr<KeyEvent> consumeKey(bool handled = true) {
776 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
777 if (event == nullptr) {
778 ADD_FAILURE() << "No event";
779 return nullptr;
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700780 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800781 if (event->getType() != InputEventType::KEY) {
782 ADD_FAILURE() << "Instead of key event, got " << event;
783 return nullptr;
784 }
785 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700786 }
787
788 void consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800789 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
790 ASSERT_NE(nullptr, keyEvent);
791 ASSERT_THAT(*keyEvent, matcher);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700792 }
793
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800794 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000795 consumeKeyEvent(AllOf(WithKeyAction(ACTION_DOWN), WithDisplayId(expectedDisplayId),
796 WithFlags(expectedFlags)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800797 }
798
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700799 void consumeKeyUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000800 consumeKeyEvent(AllOf(WithKeyAction(ACTION_UP), WithDisplayId(expectedDisplayId),
801 WithFlags(expectedFlags)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700802 }
803
Svet Ganov5d3bc372020-01-26 23:11:07 -0800804 void consumeMotionCancel(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000805 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800806 consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(expectedDisplayId),
807 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800808 }
809
810 void consumeMotionMove(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000811 int32_t expectedFlags = 0) {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800812 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
813 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800814 }
815
816 void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000817 int32_t expectedFlags = 0) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +0000818 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
819 }
820
821 void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
822 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000823 consumeMotionEvent(
824 AllOf(WithMotionAction(ACTION_DOWN),
825 testing::Conditional(expectedDisplayId.has_value(),
826 WithDisplayId(*expectedDisplayId), testing::_),
827 testing::Conditional(expectedFlags.has_value(), WithFlags(*expectedFlags),
828 testing::_)));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -0800829 }
830
Svet Ganov5d3bc372020-01-26 23:11:07 -0800831 void consumeMotionPointerDown(int32_t pointerIdx,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000832 int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
833 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000834 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000835 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000836 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
837 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800838 }
839
840 void consumeMotionPointerUp(int32_t pointerIdx, int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000841 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000842 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000843 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000844 consumeMotionEvent(AllOf(WithMotionAction(action), WithDisplayId(expectedDisplayId),
845 WithFlags(expectedFlags)));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800846 }
847
848 void consumeMotionUp(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000849 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000850 consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDisplayId(expectedDisplayId),
851 WithFlags(expectedFlags)));
Michael Wright3a240c42019-12-10 20:53:41 +0000852 }
853
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500854 void consumeMotionOutside(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
855 int32_t expectedFlags = 0) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000856 consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
857 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -0500858 }
859
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000860 void consumeMotionOutsideWithZeroedCoords() {
861 consumeMotionEvent(
862 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE), WithRawCoords(0, 0)));
Prabir Pradhandfabf8a2022-01-21 08:19:30 -0800863 }
864
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100865 void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
866 ASSERT_NE(mInputReceiver, nullptr)
867 << "Cannot consume events from a window with no receiver";
868 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
869 }
870
Prabir Pradhan99987712020-11-10 18:43:05 -0800871 void consumeCaptureEvent(bool hasCapture) {
872 ASSERT_NE(mInputReceiver, nullptr)
873 << "Cannot consume events from a window with no receiver";
874 mInputReceiver->consumeCaptureEvent(hasCapture);
875 }
876
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800877 std::unique_ptr<MotionEvent> consumeMotionEvent(
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000878 const ::testing::Matcher<MotionEvent>& matcher = testing::_) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800879 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
880 if (event == nullptr) {
881 ADD_FAILURE() << "No event";
882 return nullptr;
Prabir Pradhan5893d362023-11-17 04:30:40 +0000883 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800884 if (event->getType() != InputEventType::MOTION) {
885 ADD_FAILURE() << "Instead of motion event, got " << *event;
886 return nullptr;
887 }
888 std::unique_ptr<MotionEvent> motionEvent =
889 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
890 EXPECT_THAT(*motionEvent, matcher);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000891 return motionEvent;
chaviwd1c23182019-12-20 18:44:56 -0800892 }
893
arthurhungb89ccb02020-12-30 16:19:01 +0800894 void consumeDragEvent(bool isExiting, float x, float y) {
895 mInputReceiver->consumeDragEvent(isExiting, x, y);
896 }
897
Antonio Kantekf16f2832021-09-28 04:39:20 +0000898 void consumeTouchModeEvent(bool inTouchMode) {
899 ASSERT_NE(mInputReceiver, nullptr)
900 << "Cannot consume events from a window with no receiver";
901 mInputReceiver->consumeTouchModeEvent(inTouchMode);
902 }
903
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800904 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000905 return receive();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700906 }
907
908 void finishEvent(uint32_t sequenceNum) {
909 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
910 mInputReceiver->finishEvent(sequenceNum);
911 }
912
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +0000913 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
914 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
915 mInputReceiver->sendTimeline(inputEventId, timeline);
916 }
917
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800918 void assertNoEvents(std::chrono::milliseconds timeout = CONSUME_TIMEOUT_NO_EVENT_EXPECTED) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500919 if (mInputReceiver == nullptr &&
Prabir Pradhan51e7db02022-02-07 06:02:57 -0800920 mInfo.inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -0500921 return; // Can't receive events if the window does not have input channel
922 }
923 ASSERT_NE(nullptr, mInputReceiver)
924 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800925 mInputReceiver->assertNoEvents(timeout);
Arthur Hungb92218b2018-08-14 12:00:21 +0800926 }
927
chaviwaf87b3e2019-10-01 16:59:28 -0700928 sp<IBinder> getToken() { return mInfo.token; }
929
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +0100930 const std::string& getName() { return mName; }
931
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000932 void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000933 mInfo.ownerPid = ownerPid;
934 mInfo.ownerUid = ownerUid;
935 }
936
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000937 gui::Pid getPid() const { return mInfo.ownerPid; }
Prabir Pradhanedd96402022-02-15 01:46:16 -0800938
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800939 void destroyReceiver() { mInputReceiver = nullptr; }
940
Prabir Pradhan07e05b62021-11-19 03:57:24 -0800941 int getChannelFd() { return mInputReceiver->getChannelFd(); }
942
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000943 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800944 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000945 if (mInputReceiver == nullptr) {
946 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
947 }
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800948 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000949 if (event == nullptr) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800950 ADD_FAILURE() << "Consume failed: no event";
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000951 }
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000952 expectReceivedEventTraced(event);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800953 return event;
Prabir Pradhan7662a8d2023-12-15 01:58:14 +0000954 }
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800955
956private:
957 FakeWindowHandle(std::string name) : mName(name){};
958 const std::string mName;
959 std::shared_ptr<FakeInputReceiver> mInputReceiver;
960 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
961 friend class sp<FakeWindowHandle>;
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000962
963 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
964 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
965 if (mInputReceiver == nullptr) {
966 ADD_FAILURE() << "Invalid receive event on window with no receiver";
967 return std::make_pair(std::nullopt, nullptr);
968 }
969 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
970 const auto& [_, event] = out;
971 expectReceivedEventTraced(event);
972 return std::move(out);
973 }
974
975 void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
976 if (!event) {
977 return;
978 }
979
980 switch (event->getType()) {
981 case InputEventType::KEY: {
Prabir Pradhan4497c862023-12-15 07:13:30 +0000982 gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000983 break;
984 }
985 case InputEventType::MOTION: {
Prabir Pradhan4497c862023-12-15 07:13:30 +0000986 gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
987 mInfo.id);
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000988 break;
989 }
990 default:
991 break;
992 }
993 }
Arthur Hung2fbf37f2018-09-13 18:16:41 +0800994};
995
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700996std::atomic<int32_t> FakeWindowHandle::sId{1};
997
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000998class FakeMonitorReceiver {
999public:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001000 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name, int32_t displayId)
1001 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001002
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001003 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001004
1005 void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001006 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
1007 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001008 }
1009
1010 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001011 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
1012 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001013 }
1014
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001015 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001016
1017 void consumeMotionDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001018 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
1019 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001020 }
1021
1022 void consumeMotionMove(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001023 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
1024 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001025 }
1026
1027 void consumeMotionUp(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001028 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
1029 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001030 }
1031
1032 void consumeMotionCancel(int32_t expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001033 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001034 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
1035 WithDisplayId(expectedDisplayId),
1036 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
1037 }
1038
1039 void consumeMotionPointerDown(int32_t pointerIdx) {
1040 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
1041 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001042 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ADISPLAY_ID_DEFAULT,
1043 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001044 }
1045
1046 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001047 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001048 }
1049
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08001050 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001051
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08001052 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001053
1054private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -07001055 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00001056};
1057
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001058static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001059 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001060 int32_t displayId = ADISPLAY_ID_NONE,
1061 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001062 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001063 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +00001064 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +08001065 KeyEvent event;
1066 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1067
1068 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -08001069 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +00001070 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
1071 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +08001072
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001073 if (!allowKeyRepeat) {
1074 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
1075 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001076 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001077 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001078}
1079
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001080static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
1081 InputEventInjectionResult result =
1082 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_NONE,
1083 InputEventInjectionSync::WAIT_FOR_RESULT, CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
1084 if (result != InputEventInjectionResult::TIMED_OUT) {
1085 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
1086 }
1087}
1088
1089static InputEventInjectionResult injectKeyDown(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001090 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001091 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001092}
1093
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001094// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
1095// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
1096// has to be woken up to process the repeating key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001097static InputEventInjectionResult injectKeyDownNoRepeat(InputDispatcher& dispatcher,
1098 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001099 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001100 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +00001101 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -08001102}
1103
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001104static InputEventInjectionResult injectKeyUp(InputDispatcher& dispatcher,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001105 int32_t displayId = ADISPLAY_ID_NONE) {
Harry Cutts33476232023-01-30 19:57:29 +00001106 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001107}
1108
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001109static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001110 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -07001111 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001112 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001113 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001114 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
1115 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -07001116}
1117
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001118static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001119 InputDispatcher& dispatcher, int32_t action, int32_t source, int32_t displayId,
1120 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001121 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07001122 AMOTION_EVENT_INVALID_CURSOR_POSITION},
1123 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001124 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +00001125 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00001126 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001127 MotionEventBuilder motionBuilder =
1128 MotionEventBuilder(action, source)
1129 .displayId(displayId)
1130 .eventTime(eventTime)
1131 .rawXCursorPosition(cursorPosition.x)
1132 .rawYCursorPosition(cursorPosition.y)
1133 .pointer(
1134 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
1135 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
1136 motionBuilder.downTime(eventTime);
1137 }
Arthur Hungb92218b2018-08-14 12:00:21 +08001138
1139 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07001140 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
1141 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +08001142}
1143
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001144static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
1145 int32_t displayId,
1146 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001147 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -07001148}
1149
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001150static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
1151 int32_t displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001152 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07001153 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +00001154}
1155
Jackal Guof9696682018-10-05 12:23:23 +08001156static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
1157 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1158 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001159 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1160 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
1161 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +08001162
1163 return args;
1164}
1165
Josep del Riob3981622023-04-18 15:49:45 +00001166static NotifyKeyArgs generateSystemShortcutArgs(int32_t action,
1167 int32_t displayId = ADISPLAY_ID_NONE) {
1168 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1169 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001170 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1171 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
1172 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001173
1174 return args;
1175}
1176
1177static NotifyKeyArgs generateAssistantKeyArgs(int32_t action,
1178 int32_t displayId = ADISPLAY_ID_NONE) {
1179 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1180 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001181 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
1182 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
1183 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +00001184
1185 return args;
1186}
1187
Prabir Pradhan678438e2023-04-13 19:32:51 +00001188[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
1189 int32_t displayId,
1190 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -08001191 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -07001192 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
1193 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
1194 }
1195
chaviwd1c23182019-12-20 18:44:56 -08001196 PointerProperties pointerProperties[pointerCount];
1197 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +08001198
chaviwd1c23182019-12-20 18:44:56 -08001199 for (size_t i = 0; i < pointerCount; i++) {
1200 pointerProperties[i].clear();
1201 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001202 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +08001203
chaviwd1c23182019-12-20 18:44:56 -08001204 pointerCoords[i].clear();
1205 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
1206 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
1207 }
Jackal Guof9696682018-10-05 12:23:23 +08001208
1209 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
1210 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001211 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
1212 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
1213 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -08001214 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001215 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -07001216 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +00001217 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +08001218
1219 return args;
1220}
1221
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001222static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
1223 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
1224}
1225
chaviwd1c23182019-12-20 18:44:56 -08001226static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId) {
1227 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
1228}
1229
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00001230static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
1231 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +00001232 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
1233 request);
Prabir Pradhan99987712020-11-10 18:43:05 -08001234}
1235
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -07001236} // namespace
1237
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001238/**
1239 * When a window unexpectedly disposes of its input channel, policy should be notified about the
1240 * broken channel.
1241 */
1242TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
1243 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1244 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001245 sp<FakeWindowHandle>::make(application, mDispatcher,
1246 "Window that breaks its input channel", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001247
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001248 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -08001249
1250 // Window closes its channel, but the window remains.
1251 window->destroyReceiver();
1252 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
1253}
1254
Arthur Hungb92218b2018-08-14 12:00:21 +08001255TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001257 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1258 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001259
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001260 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001262 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001263 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001264
1265 // Window should receive motion event.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001266 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001267}
1268
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -08001269using InputDispatcherDeathTest = InputDispatcherTest;
1270
1271/**
1272 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
1273 * should crash.
1274 */
1275TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
1276 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1277 ScopedSilentDeath _silentDeath;
1278
1279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1280 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1281 "Fake Window", ADISPLAY_ID_DEFAULT);
1282 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
1283 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
1284 "Incorrect WindowInfosUpdate provided");
1285}
1286
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001287TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
1288 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001289 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1290 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001291
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001292 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001293 // Inject a MotionEvent to an unknown display.
1294 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001295 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_NONE))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07001296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1297
1298 // Window should receive motion event.
1299 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1300}
1301
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001302/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001303 * Calling onWindowInfosChanged once should not cause any issues.
1304 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001305 * called twice.
1306 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08001307TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -07001308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001309 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1310 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001311 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001312
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001313 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001315 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001316 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001318
1319 // Window should receive motion event.
1320 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1321}
1322
1323/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001324 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001325 */
1326TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001328 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
1329 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001330 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001331
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001332 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1333 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001334 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001335 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001336 {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001337 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07001338
1339 // Window should receive motion event.
1340 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1341}
1342
Arthur Hungb92218b2018-08-14 12:00:21 +08001343// The foreground window should receive the first touch down event.
1344TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07001345 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001346 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001347 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10001348 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001349 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001350
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001351 mDispatcher->onWindowInfosChanged(
1352 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001354 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08001355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08001356
1357 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08001358 windowTop->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08001359 windowSecond->assertNoEvents();
1360}
1361
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001362/**
1363 * Two windows: A top window, and a wallpaper behind the window.
1364 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
1365 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001366 * 1. foregroundWindow <-- dup touch to wallpaper
1367 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001368 */
1369TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
1370 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1371 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001372 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001373 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001374 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001375 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001376 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001377
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001378 mDispatcher->onWindowInfosChanged(
1379 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001381 injectMotionEvent(*mDispatcher,
1382 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1383 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
1384 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1386
1387 // Both foreground window and its wallpaper should receive the touch down
1388 foregroundWindow->consumeMotionDown();
1389 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1390
1391 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001392 injectMotionEvent(*mDispatcher,
1393 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1394 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
1395 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001396 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1397
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -08001398 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001399 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1400
1401 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001402 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001403 foregroundWindow->consumeMotionCancel();
1404 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1405 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1406}
1407
1408/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001409 * Two fingers down on the window, and lift off the first finger.
1410 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
1411 * contains a single pointer.
1412 */
1413TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
1414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1415 sp<FakeWindowHandle> window =
1416 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1417
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001419 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00001420 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1421 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1422 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001423 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001424 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1425 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1426 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1427 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001428 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001429 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1430 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1431 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
1432 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001433 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1434 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1435 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
1436
1437 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001438 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08001439 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
1440 window->consumeMotionEvent(
1441 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
1442}
1443
1444/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001445 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
1446 * with the following differences:
1447 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
1448 * clean up the connection.
1449 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
1450 * Ensure that there's no crash in the dispatcher.
1451 */
1452TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
1453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1454 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001455 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001456 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001457 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001458 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001459 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001460
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001461 mDispatcher->onWindowInfosChanged(
1462 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001463 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001464 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001465 {100, 200}))
1466 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1467
1468 // Both foreground window and its wallpaper should receive the touch down
1469 foregroundWindow->consumeMotionDown();
1470 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1471
1472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001473 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001474 ADISPLAY_ID_DEFAULT, {110, 200}))
1475 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1476
1477 foregroundWindow->consumeMotionMove();
1478 wallpaperWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1479
1480 // Wallpaper closes its channel, but the window remains.
1481 wallpaperWindow->destroyReceiver();
1482 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
1483
1484 // Now the foreground window goes away, but the wallpaper stays, even though its channel
1485 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001486 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001487 foregroundWindow->consumeMotionCancel();
1488}
1489
Arthur Hungc539dbb2022-12-08 07:45:36 +00001490class ShouldSplitTouchFixture : public InputDispatcherTest,
1491 public ::testing::WithParamInterface<bool> {};
1492INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1493 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001494/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001495 * A single window that receives touch (on top), and a wallpaper window underneath it.
1496 * The top window gets a multitouch gesture.
1497 * Ensure that wallpaper gets the same gesture.
1498 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001499TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001500 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001501 sp<FakeWindowHandle> foregroundWindow =
1502 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
1503 foregroundWindow->setDupTouchToWallpaper(true);
1504 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001505
1506 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001507 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001508 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001509
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001510 mDispatcher->onWindowInfosChanged(
1511 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001512
1513 // Touch down on top window
1514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001515 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001516 {100, 100}))
1517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1518
1519 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001520 foregroundWindow->consumeMotionDown();
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001521 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1522
1523 // Second finger down on the top window
1524 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001525 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001526 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001527 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1528 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001529 .build();
1530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001531 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001532 InputEventInjectionSync::WAIT_FOR_RESULT))
1533 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1534
Harry Cutts33476232023-01-30 19:57:29 +00001535 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
1536 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001537 expectedWallpaperFlags);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001538
1539 const MotionEvent secondFingerUpEvent =
1540 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
1541 .displayId(ADISPLAY_ID_DEFAULT)
1542 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001543 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1544 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001545 .build();
1546 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001547 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001548 InputEventInjectionSync::WAIT_FOR_RESULT))
1549 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1550 foregroundWindow->consumeMotionPointerUp(0);
1551 wallpaperWindow->consumeMotionPointerUp(0, ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1552
1553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001554 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001555 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1556 AINPUT_SOURCE_TOUCHSCREEN)
1557 .displayId(ADISPLAY_ID_DEFAULT)
1558 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001559 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001560 .x(100)
1561 .y(100))
1562 .build(),
1563 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001564 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1565 foregroundWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
1566 wallpaperWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001567}
1568
1569/**
1570 * Two windows: a window on the left and window on the right.
1571 * A third window, wallpaper, is behind both windows, and spans both top windows.
1572 * The first touch down goes to the left window. A second pointer touches down on the right window.
1573 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1574 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1575 * ACTION_POINTER_DOWN(1).
1576 */
1577TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1578 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1579 sp<FakeWindowHandle> leftWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001580 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001581 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001582 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001583
1584 sp<FakeWindowHandle> rightWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001585 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001586 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001587 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001588
1589 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07001590 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001591 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001592 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001593
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001594 mDispatcher->onWindowInfosChanged(
1595 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1596 {},
1597 0,
1598 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001599
1600 // Touch down on left window
1601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001602 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001603 {100, 100}))
1604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1605
1606 // Both foreground window and its wallpaper should receive the touch down
1607 leftWindow->consumeMotionDown();
1608 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1609
1610 // Second finger down on the right window
1611 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001612 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001613 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001614 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1615 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001616 .build();
1617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001619 InputEventInjectionSync::WAIT_FOR_RESULT))
1620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1621
1622 leftWindow->consumeMotionMove();
1623 // Since the touch is split, right window gets ACTION_DOWN
1624 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +00001625 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001626 expectedWallpaperFlags);
1627
1628 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001629 mDispatcher->onWindowInfosChanged(
1630 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001631 leftWindow->consumeMotionCancel();
1632 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
1633 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1634
1635 // The pointer that's still down on the right window moves, and goes to the right window only.
1636 // As far as the dispatcher's concerned though, both pointers are still present.
1637 const MotionEvent secondFingerMoveEvent =
1638 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1639 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001640 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1641 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001642 .build();
1643 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001644 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001645 InputEventInjectionSync::WAIT_FOR_RESULT));
1646 rightWindow->consumeMotionMove();
1647
1648 leftWindow->assertNoEvents();
1649 rightWindow->assertNoEvents();
1650 wallpaperWindow->assertNoEvents();
1651}
1652
Arthur Hungc539dbb2022-12-08 07:45:36 +00001653/**
1654 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1655 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1656 * The right window should receive ACTION_DOWN.
1657 */
1658TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001660 sp<FakeWindowHandle> leftWindow =
1661 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1662 leftWindow->setFrame(Rect(0, 0, 200, 200));
1663 leftWindow->setDupTouchToWallpaper(true);
1664 leftWindow->setSlippery(true);
1665
1666 sp<FakeWindowHandle> rightWindow =
1667 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1668 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001669
1670 sp<FakeWindowHandle> wallpaperWindow =
1671 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
1672 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001674 mDispatcher->onWindowInfosChanged(
1675 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1676 {},
1677 0,
1678 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001679
Arthur Hungc539dbb2022-12-08 07:45:36 +00001680 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001682 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001683 {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001685
1686 // Both foreground window and its wallpaper should receive the touch down
1687 leftWindow->consumeMotionDown();
Arthur Hung74c248d2022-11-23 07:09:59 +00001688 wallpaperWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
1689
Arthur Hungc539dbb2022-12-08 07:45:36 +00001690 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001691 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001692 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001693 ADISPLAY_ID_DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001694 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1695
Arthur Hungc539dbb2022-12-08 07:45:36 +00001696 leftWindow->consumeMotionCancel();
1697 rightWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
1698 wallpaperWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Arthur Hung74c248d2022-11-23 07:09:59 +00001699}
1700
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001701/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001702 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1703 * interactive, it might stop sending this flag.
1704 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1705 * to have a consistent input stream.
1706 *
1707 * Test procedure:
1708 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1709 * DOWN (new gesture).
1710 *
1711 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1712 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1713 *
1714 * We technically just need a single window here, but we are using two windows (spy on top and a
1715 * regular window below) to emulate the actual situation where it happens on the device.
1716 */
1717TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1719 sp<FakeWindowHandle> spyWindow =
1720 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
1721 spyWindow->setFrame(Rect(0, 0, 200, 200));
1722 spyWindow->setTrustedOverlay(true);
1723 spyWindow->setSpy(true);
1724
1725 sp<FakeWindowHandle> window =
1726 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1727 window->setFrame(Rect(0, 0, 200, 200));
1728
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001729 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001730 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001731
1732 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001733 mDispatcher->notifyMotion(
1734 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1735 .deviceId(touchDeviceId)
1736 .policyFlags(DEFAULT_POLICY_FLAGS)
1737 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1738 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001739
Prabir Pradhan678438e2023-04-13 19:32:51 +00001740 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1741 .deviceId(touchDeviceId)
1742 .policyFlags(DEFAULT_POLICY_FLAGS)
1743 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1744 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1745 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001746 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1747 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1748 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1749 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1750
1751 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001752 mDispatcher->notifyMotion(
1753 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1754 .deviceId(touchDeviceId)
1755 .policyFlags(0)
1756 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1757 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1758 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001759 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1760 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1761
1762 // We don't need to reset the device to reproduce the issue, but the reset event typically
1763 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001764 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001765
1766 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001767 mDispatcher->notifyMotion(
1768 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1769 .deviceId(touchDeviceId)
1770 .policyFlags(DEFAULT_POLICY_FLAGS)
1771 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1772 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001773 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1774 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1775
1776 // No more events
1777 spyWindow->assertNoEvents();
1778 window->assertNoEvents();
1779}
1780
1781/**
Linnan Li907ae732023-09-05 17:14:21 +08001782 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1783 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1784 * interactive, it might stop sending this flag.
1785 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1786 * the consistency of the hover event in this case.
1787 *
1788 * Test procedure:
1789 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1790 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1791 *
1792 * We expect to receive two full streams of hover events.
1793 */
1794TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1796
1797 sp<FakeWindowHandle> window =
1798 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1799 window->setFrame(Rect(0, 0, 300, 300));
1800
1801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1802
1803 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1804 .policyFlags(DEFAULT_POLICY_FLAGS)
1805 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1806 .build());
1807 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1808
1809 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1810 .policyFlags(DEFAULT_POLICY_FLAGS)
1811 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1812 .build());
1813 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1814
1815 // Send hover exit without the default policy flags.
1816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1817 .policyFlags(0)
1818 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1819 .build());
1820
1821 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1822
1823 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1824 // right event.
1825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1826 .policyFlags(DEFAULT_POLICY_FLAGS)
1827 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1828 .build());
1829 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1830
1831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1832 .policyFlags(DEFAULT_POLICY_FLAGS)
1833 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1834 .build());
1835 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1836
1837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1838 .policyFlags(DEFAULT_POLICY_FLAGS)
1839 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1840 .build());
1841 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1842}
1843
1844/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001845 * Two windows: a window on the left and a window on the right.
1846 * Mouse is hovered from the right window into the left window.
1847 * Next, we tap on the left window, where the cursor was last seen.
1848 * The second tap is done onto the right window.
1849 * The mouse and tap are from two different devices.
1850 * We technically don't need to set the downtime / eventtime for these events, but setting these
1851 * explicitly helps during debugging.
1852 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1853 * In the buggy implementation, a tap on the right window would cause a crash.
1854 */
1855TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1856 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1857 sp<FakeWindowHandle> leftWindow =
1858 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
1859 leftWindow->setFrame(Rect(0, 0, 200, 200));
1860
1861 sp<FakeWindowHandle> rightWindow =
1862 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
1863 rightWindow->setFrame(Rect(200, 0, 400, 200));
1864
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001865 mDispatcher->onWindowInfosChanged(
1866 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001867 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1868 // stale.
1869 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1870 const int32_t mouseDeviceId = 6;
1871 const int32_t touchDeviceId = 4;
1872 // Move the cursor from right
1873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001874 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001875 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1876 AINPUT_SOURCE_MOUSE)
1877 .deviceId(mouseDeviceId)
1878 .downTime(baseTime + 10)
1879 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001880 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001881 .build()));
1882 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1883
1884 // .. to the left window
1885 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001886 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001887 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1888 AINPUT_SOURCE_MOUSE)
1889 .deviceId(mouseDeviceId)
1890 .downTime(baseTime + 10)
1891 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001892 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001893 .build()));
1894 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1895 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1896 // Now tap the left window
1897 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001898 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001899 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1900 AINPUT_SOURCE_TOUCHSCREEN)
1901 .deviceId(touchDeviceId)
1902 .downTime(baseTime + 40)
1903 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001904 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001905 .build()));
1906 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1907 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1908
1909 // release tap
1910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001911 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001912 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1913 AINPUT_SOURCE_TOUCHSCREEN)
1914 .deviceId(touchDeviceId)
1915 .downTime(baseTime + 40)
1916 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001917 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001918 .build()));
1919 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1920
1921 // Tap the window on the right
1922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001923 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001924 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1925 AINPUT_SOURCE_TOUCHSCREEN)
1926 .deviceId(touchDeviceId)
1927 .downTime(baseTime + 60)
1928 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001929 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001930 .build()));
1931 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1932
1933 // release tap
1934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001935 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001936 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1937 AINPUT_SOURCE_TOUCHSCREEN)
1938 .deviceId(touchDeviceId)
1939 .downTime(baseTime + 60)
1940 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001941 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001942 .build()));
1943 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1944
1945 // No more events
1946 leftWindow->assertNoEvents();
1947 rightWindow->assertNoEvents();
1948}
1949
1950/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001951 * Start hovering in a window. While this hover is still active, make another window appear on top.
1952 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1953 * While the top window is present, the hovering is stopped.
1954 * Later, hovering gets resumed again.
1955 * Ensure that new hover gesture is handled correctly.
1956 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1957 * to the window that's currently being hovered over.
1958 */
1959TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1960 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1961 sp<FakeWindowHandle> window =
1962 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
1963 window->setFrame(Rect(0, 0, 200, 200));
1964
1965 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001966 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001967
1968 // Start hovering in the window
1969 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1970 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1971 .build());
1972 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1973
1974 // Now, an obscuring window appears!
1975 sp<FakeWindowHandle> obscuringWindow =
1976 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
1977 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001978 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001979 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1980 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1981 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1982 obscuringWindow->setNoInputChannel(true);
1983 obscuringWindow->setFocusable(false);
1984 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001985 mDispatcher->onWindowInfosChanged(
1986 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001987
1988 // While this new obscuring window is present, the hovering is stopped
1989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1990 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1991 .build());
1992 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1993
1994 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001995 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001996
1997 // And a new hover gesture starts.
1998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1999 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2000 .build());
2001 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2002}
2003
2004/**
2005 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
2006 * the obscuring window.
2007 */
2008TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
2009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2010 sp<FakeWindowHandle> window =
2011 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2012 window->setFrame(Rect(0, 0, 200, 200));
2013
2014 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002015 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002016
2017 // Start hovering in the window
2018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2019 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2020 .build());
2021 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2022
2023 // Now, an obscuring window appears!
2024 sp<FakeWindowHandle> obscuringWindow =
2025 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
2026 ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00002027 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002028 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
2029 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
2030 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
2031 obscuringWindow->setNoInputChannel(true);
2032 obscuringWindow->setFocusable(false);
2033 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002034 mDispatcher->onWindowInfosChanged(
2035 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002036
2037 // While this new obscuring window is present, the hovering continues. The event can't go to the
2038 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
2039 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2040 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2041 .build());
2042 obscuringWindow->assertNoEvents();
2043 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2044
2045 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002046 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07002047
2048 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
2049 // so it should generate a HOVER_ENTER
2050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2051 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2052 .build());
2053 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2054
2055 // Now the MOVE should be getting dispatched normally
2056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2057 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2058 .build());
2059 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2060}
2061
2062/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002063 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
2064 * events are delivered to the window.
2065 */
2066TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
2067 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2068 sp<FakeWindowHandle> window =
2069 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2070 window->setFrame(Rect(0, 0, 200, 200));
2071 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2072
2073 // Start hovering in the window
2074 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2075 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2076 .build());
2077 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2078
2079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2080 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2081 .build());
2082 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2083
2084 // Scroll with the mouse
2085 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
2086 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2087 .build());
2088 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
2089}
2090
2091using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2092
2093/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002094 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2095 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002096 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002097TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2099 sp<FakeWindowHandle> window =
2100 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2101 window->setFrame(Rect(0, 0, 200, 200));
2102
2103 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2104
2105 constexpr int32_t touchDeviceId = 4;
2106 constexpr int32_t stylusDeviceId = 2;
2107
2108 // Stylus down
2109 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2110 .deviceId(stylusDeviceId)
2111 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2112 .build());
2113 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2114
2115 // Touch down
2116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2117 .deviceId(touchDeviceId)
2118 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2119 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002120
2121 // Touch move
2122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2123 .deviceId(touchDeviceId)
2124 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2125 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002126 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002127
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002128 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002129 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2130 .deviceId(stylusDeviceId)
2131 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2132 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002133 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2134 WithCoords(101, 111)));
2135
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002136 window->assertNoEvents();
2137}
2138
2139/**
2140 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002141 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002142 * Similar test as above, but with added SPY window.
2143 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002144TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002145 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2146 sp<FakeWindowHandle> window =
2147 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2148 sp<FakeWindowHandle> spyWindow =
2149 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2150 spyWindow->setFrame(Rect(0, 0, 200, 200));
2151 spyWindow->setTrustedOverlay(true);
2152 spyWindow->setSpy(true);
2153 window->setFrame(Rect(0, 0, 200, 200));
2154
2155 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2156
2157 constexpr int32_t touchDeviceId = 4;
2158 constexpr int32_t stylusDeviceId = 2;
2159
2160 // Stylus down
2161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2162 .deviceId(stylusDeviceId)
2163 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2164 .build());
2165 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2166 spyWindow->consumeMotionEvent(
2167 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2168
2169 // Touch down
2170 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2171 .deviceId(touchDeviceId)
2172 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2173 .build());
2174
2175 // Touch move
2176 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2177 .deviceId(touchDeviceId)
2178 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2179 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002180
2181 // Touch is ignored because stylus is already down
2182
2183 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002184 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2185 .deviceId(stylusDeviceId)
2186 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2187 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002188 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2189 WithCoords(101, 111)));
2190 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2191 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002192
2193 window->assertNoEvents();
2194 spyWindow->assertNoEvents();
2195}
2196
2197/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002198 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002199 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002200 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002201TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002202 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2203 sp<FakeWindowHandle> window =
2204 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2205 window->setFrame(Rect(0, 0, 200, 200));
2206
2207 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2208
2209 constexpr int32_t touchDeviceId = 4;
2210 constexpr int32_t stylusDeviceId = 2;
2211
2212 // Stylus down on the window
2213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2214 .deviceId(stylusDeviceId)
2215 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2216 .build());
2217 window->consumeMotionEvent(
2218 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2219
2220 // Touch down on window
2221 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2222 .deviceId(touchDeviceId)
2223 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2224 .build());
2225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2226 .deviceId(touchDeviceId)
2227 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2228 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002229
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002230 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002231
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002232 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2234 .deviceId(stylusDeviceId)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2236 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2238 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002239
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002240 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002241 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2242 .deviceId(touchDeviceId)
2243 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2244 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002245 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002246}
2247
2248/**
2249 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002250 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002251 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002252TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002253 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2254 sp<FakeWindowHandle> window =
2255 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2256 window->setFrame(Rect(0, 0, 200, 200));
2257
2258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2259
2260 constexpr int32_t touchDeviceId = 4;
2261 constexpr int32_t stylusDeviceId = 2;
2262
2263 // Touch down on window
2264 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2265 .deviceId(touchDeviceId)
2266 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2267 .build());
2268 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2269 .deviceId(touchDeviceId)
2270 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2271 .build());
2272 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2273 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2274
2275 // Stylus hover on the window
2276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2277 .deviceId(stylusDeviceId)
2278 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2279 .build());
2280 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2281 .deviceId(stylusDeviceId)
2282 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2283 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002284 // Stylus hover movement causes touch to be canceled
2285 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2286 WithCoords(141, 146)));
2287 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2288 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2289 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2290 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002291
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002292 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002293 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2294 .deviceId(touchDeviceId)
2295 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2296 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002297
2298 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002299}
2300
2301/**
2302 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2303 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2304 * become active.
2305 */
2306TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
2307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2308 sp<FakeWindowHandle> window =
2309 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2310 window->setFrame(Rect(0, 0, 200, 200));
2311
2312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2313
2314 constexpr int32_t stylusDeviceId1 = 3;
2315 constexpr int32_t stylusDeviceId2 = 5;
2316
2317 // Touch down on window
2318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2319 .deviceId(stylusDeviceId1)
2320 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2321 .build());
2322 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2323 .deviceId(stylusDeviceId1)
2324 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2325 .build());
2326 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2327 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2328
2329 // Second stylus down
2330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2331 .deviceId(stylusDeviceId2)
2332 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2333 .build());
2334 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2335 .deviceId(stylusDeviceId2)
2336 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2337 .build());
2338
2339 // First stylus is canceled, second one takes over.
2340 window->consumeMotionEvent(
2341 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2342 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2343 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2344
2345 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2346 .deviceId(stylusDeviceId1)
2347 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2348 .build());
2349 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002350 window->assertNoEvents();
2351}
2352
2353/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002354 * One window. Touch down on the window. Then, stylus down on the window from another device.
2355 * Ensure that is canceled, because stylus down should be preferred over touch.
2356 */
2357TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
2358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2359 sp<FakeWindowHandle> window =
2360 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2361 window->setFrame(Rect(0, 0, 200, 200));
2362
2363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2364
2365 constexpr int32_t touchDeviceId = 4;
2366 constexpr int32_t stylusDeviceId = 2;
2367
2368 // Touch down on window
2369 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2370 .deviceId(touchDeviceId)
2371 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2372 .build());
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2374 .deviceId(touchDeviceId)
2375 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2376 .build());
2377 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2378 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2379
2380 // Stylus down on the window
2381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2382 .deviceId(stylusDeviceId)
2383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2384 .build());
2385 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2386 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2387
2388 // Subsequent stylus movements are delivered correctly
2389 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2390 .deviceId(stylusDeviceId)
2391 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2392 .build());
2393 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2394 WithCoords(101, 111)));
2395}
2396
2397/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002398 * Two windows: a window on the left and a window on the right.
2399 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2400 * down. Then, on the left window, also place second touch pointer down.
2401 * This test tries to reproduce a crash.
2402 * In the buggy implementation, second pointer down on the left window would cause a crash.
2403 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002404TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2406 sp<FakeWindowHandle> leftWindow =
2407 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2408 leftWindow->setFrame(Rect(0, 0, 200, 200));
2409
2410 sp<FakeWindowHandle> rightWindow =
2411 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2412 rightWindow->setFrame(Rect(200, 0, 400, 200));
2413
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002414 mDispatcher->onWindowInfosChanged(
2415 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002416
2417 const int32_t touchDeviceId = 4;
2418 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002419
2420 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2422 .deviceId(mouseDeviceId)
2423 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2424 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002425 leftWindow->consumeMotionEvent(
2426 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2427
2428 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002429 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2430 .deviceId(mouseDeviceId)
2431 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2432 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2433 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002434
2435 leftWindow->consumeMotionEvent(
2436 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2437 leftWindow->consumeMotionEvent(
2438 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2439
Prabir Pradhan678438e2023-04-13 19:32:51 +00002440 mDispatcher->notifyMotion(
2441 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2442 .deviceId(mouseDeviceId)
2443 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2444 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2445 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2446 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002447 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2448
2449 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2451 .deviceId(touchDeviceId)
2452 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2453 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002454 leftWindow->assertNoEvents();
2455
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002456 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2457
2458 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002459 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2460 .deviceId(touchDeviceId)
2461 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2462 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2463 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002464 // Since this is now a new splittable pointer going down on the left window, and it's coming
2465 // from a different device, the current gesture in the left window (pointer down) should first
2466 // be canceled.
2467 leftWindow->consumeMotionEvent(
2468 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002469 leftWindow->consumeMotionEvent(
2470 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2471 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2472 // current implementation.
2473 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2474 rightWindow->consumeMotionEvent(
2475 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2476
2477 leftWindow->assertNoEvents();
2478 rightWindow->assertNoEvents();
2479}
2480
2481/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002482 * Two windows: a window on the left and a window on the right.
2483 * Mouse is hovered on the left window and stylus is hovered on the right window.
2484 */
2485TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2487 sp<FakeWindowHandle> leftWindow =
2488 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2489 leftWindow->setFrame(Rect(0, 0, 200, 200));
2490
2491 sp<FakeWindowHandle> rightWindow =
2492 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2493 rightWindow->setFrame(Rect(200, 0, 400, 200));
2494
2495 mDispatcher->onWindowInfosChanged(
2496 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2497
2498 const int32_t stylusDeviceId = 3;
2499 const int32_t mouseDeviceId = 6;
2500
2501 // Start hovering over the left window
2502 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2503 .deviceId(mouseDeviceId)
2504 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2505 .build());
2506 leftWindow->consumeMotionEvent(
2507 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2508
2509 // Stylus hovered on right window
2510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2511 .deviceId(stylusDeviceId)
2512 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2513 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002514 rightWindow->consumeMotionEvent(
2515 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2516
2517 // Subsequent HOVER_MOVE events are dispatched correctly.
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2519 .deviceId(mouseDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2521 .build());
2522 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002523 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002524
2525 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2526 .deviceId(stylusDeviceId)
2527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2528 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002529 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002530 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002531
2532 leftWindow->assertNoEvents();
2533 rightWindow->assertNoEvents();
2534}
2535
2536/**
2537 * Three windows: a window on the left and a window on the right.
2538 * And a spy window that's positioned above all of them.
2539 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2540 * Check the stream that's received by the spy.
2541 */
2542TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2544
2545 sp<FakeWindowHandle> spyWindow =
2546 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2547 spyWindow->setFrame(Rect(0, 0, 400, 400));
2548 spyWindow->setTrustedOverlay(true);
2549 spyWindow->setSpy(true);
2550
2551 sp<FakeWindowHandle> leftWindow =
2552 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2553 leftWindow->setFrame(Rect(0, 0, 200, 200));
2554
2555 sp<FakeWindowHandle> rightWindow =
2556 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2557
2558 rightWindow->setFrame(Rect(200, 0, 400, 200));
2559
2560 mDispatcher->onWindowInfosChanged(
2561 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2562
2563 const int32_t stylusDeviceId = 1;
2564 const int32_t touchDeviceId = 2;
2565
2566 // Stylus down on the left window
2567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2568 .deviceId(stylusDeviceId)
2569 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2570 .build());
2571 leftWindow->consumeMotionEvent(
2572 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2573 spyWindow->consumeMotionEvent(
2574 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2575
2576 // Touch down on the right window
2577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2578 .deviceId(touchDeviceId)
2579 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2580 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002581 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002582 rightWindow->consumeMotionEvent(
2583 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002584
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002585 // Spy window does not receive touch events, because stylus events take precedence, and it
2586 // already has an active stylus gesture.
2587
2588 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2590 .deviceId(stylusDeviceId)
2591 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2592 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002593 leftWindow->consumeMotionEvent(
2594 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2595 spyWindow->consumeMotionEvent(
2596 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002597
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002598 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2600 .deviceId(touchDeviceId)
2601 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2602 .build());
2603 rightWindow->consumeMotionEvent(
2604 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002605
2606 spyWindow->assertNoEvents();
2607 leftWindow->assertNoEvents();
2608 rightWindow->assertNoEvents();
2609}
2610
2611/**
2612 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2613 * both.
2614 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002615 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002616 * At the same time, left and right should be getting independent streams of hovering and touch,
2617 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002618 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002619TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002620 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2621
2622 sp<FakeWindowHandle> spyWindow =
2623 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
2624 spyWindow->setFrame(Rect(0, 0, 400, 400));
2625 spyWindow->setTrustedOverlay(true);
2626 spyWindow->setSpy(true);
2627
2628 sp<FakeWindowHandle> leftWindow =
2629 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2630 leftWindow->setFrame(Rect(0, 0, 200, 200));
2631
2632 sp<FakeWindowHandle> rightWindow =
2633 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2634 rightWindow->setFrame(Rect(200, 0, 400, 200));
2635
2636 mDispatcher->onWindowInfosChanged(
2637 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2638
2639 const int32_t stylusDeviceId = 1;
2640 const int32_t touchDeviceId = 2;
2641
2642 // Stylus hover on the left window
2643 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2644 .deviceId(stylusDeviceId)
2645 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2646 .build());
2647 leftWindow->consumeMotionEvent(
2648 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2649 spyWindow->consumeMotionEvent(
2650 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2651
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002652 // Touch down on the right window. Spy doesn't receive this touch because it already has
2653 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2655 .deviceId(touchDeviceId)
2656 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2657 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002658 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002659 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002660 rightWindow->consumeMotionEvent(
2661 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2662
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002663 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2665 .deviceId(stylusDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2667 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002668 leftWindow->consumeMotionEvent(
2669 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002670 spyWindow->consumeMotionEvent(
2671 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002672
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002673 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2675 .deviceId(touchDeviceId)
2676 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2677 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002678 rightWindow->consumeMotionEvent(
2679 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2680
2681 spyWindow->assertNoEvents();
2682 leftWindow->assertNoEvents();
2683 rightWindow->assertNoEvents();
2684}
2685
2686/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002687 * On a single window, use two different devices: mouse and touch.
2688 * Touch happens first, with two pointers going down, and then the first pointer leaving.
2689 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
2690 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
2691 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
2692 * represent a new gesture.
2693 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002694TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002695 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2696 sp<FakeWindowHandle> window =
2697 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2698 window->setFrame(Rect(0, 0, 400, 400));
2699
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002700 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002701
2702 const int32_t touchDeviceId = 4;
2703 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002704
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08002705 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2707 .deviceId(touchDeviceId)
2708 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2709 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002710 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002711 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2712 .deviceId(touchDeviceId)
2713 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2714 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2715 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002716 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00002717 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
2718 .deviceId(touchDeviceId)
2719 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2720 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2721 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002722 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2723 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
2724 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
2725
2726 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00002727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2728 .deviceId(mouseDeviceId)
2729 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2730 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2731 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002732
2733 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08002734 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002735 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2736
Prabir Pradhan678438e2023-04-13 19:32:51 +00002737 mDispatcher->notifyMotion(
2738 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2739 .deviceId(mouseDeviceId)
2740 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2741 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2742 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
2743 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002744 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2745
2746 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002747 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2748 .deviceId(touchDeviceId)
2749 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2750 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
2751 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002752 // Since we already canceled this touch gesture, it will be ignored until a completely new
2753 // gesture is started. This is easier to implement than trying to keep track of the new pointer
2754 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
2755 // However, mouse movements should continue to work.
2756 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
2757 .deviceId(mouseDeviceId)
2758 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2759 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
2760 .build());
2761 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
2762
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002763 window->assertNoEvents();
2764}
2765
2766/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002767 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
2768 * the injected event.
2769 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002770TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2772 sp<FakeWindowHandle> window =
2773 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2774 window->setFrame(Rect(0, 0, 400, 400));
2775
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002776 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002777
2778 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002779 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
2780 // completion.
2781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002782 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002783 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2784 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002785 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002786 .build()));
2787 window->consumeMotionEvent(
2788 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2789
2790 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
2791 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00002792 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2793 .deviceId(touchDeviceId)
2794 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2795 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08002796
2797 window->consumeMotionEvent(
2798 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
2799 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2800}
2801
2802/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002803 * This test is similar to the test above, but the sequence of injected events is different.
2804 *
2805 * Two windows: a window on the left and a window on the right.
2806 * Mouse is hovered over the left window.
2807 * Next, we tap on the left window, where the cursor was last seen.
2808 *
2809 * After that, we inject one finger down onto the right window, and then a second finger down onto
2810 * the left window.
2811 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
2812 * window (first), and then another on the left window (second).
2813 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
2814 * In the buggy implementation, second finger down on the left window would cause a crash.
2815 */
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002816TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002817 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2818 sp<FakeWindowHandle> leftWindow =
2819 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
2820 leftWindow->setFrame(Rect(0, 0, 200, 200));
2821
2822 sp<FakeWindowHandle> rightWindow =
2823 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
2824 rightWindow->setFrame(Rect(200, 0, 400, 200));
2825
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002826 mDispatcher->onWindowInfosChanged(
2827 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002828
2829 const int32_t mouseDeviceId = 6;
2830 const int32_t touchDeviceId = 4;
2831 // Hover over the left window. Keep the cursor there.
2832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002833 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002834 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
2835 AINPUT_SOURCE_MOUSE)
2836 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002837 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002838 .build()));
2839 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
2840
2841 // Tap on left window
2842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002843 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002844 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2845 AINPUT_SOURCE_TOUCHSCREEN)
2846 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002847 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002848 .build()));
2849
2850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002851 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002852 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2853 AINPUT_SOURCE_TOUCHSCREEN)
2854 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002855 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002856 .build()));
2857 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
2858 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2859 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
2860
2861 // First finger down on right window
2862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002863 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002864 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
2865 AINPUT_SOURCE_TOUCHSCREEN)
2866 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002867 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002868 .build()));
2869 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2870
2871 // Second finger down on the left window
2872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002873 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002874 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2875 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002876 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2877 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08002878 .build()));
2879 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
2880 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
2881
2882 // No more events
2883 leftWindow->assertNoEvents();
2884 rightWindow->assertNoEvents();
2885}
2886
2887/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002888 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
2889 * While the touch is down, new hover events from the stylus device should be ignored. After the
2890 * touch is gone, stylus hovering should start working again.
2891 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002892TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002893 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2894 sp<FakeWindowHandle> window =
2895 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
2896 window->setFrame(Rect(0, 0, 200, 200));
2897
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002899
2900 const int32_t stylusDeviceId = 5;
2901 const int32_t touchDeviceId = 4;
2902 // Start hovering with stylus
2903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002904 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002905 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002906 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002907 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002908 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002909 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002910
2911 // Finger down on the window
2912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002913 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002914 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002915 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002916 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002917 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002918 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002919
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002920 // Continue hovering with stylus.
2921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002922 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002923 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2924 AINPUT_SOURCE_STYLUS)
2925 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002926 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002927 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002928 // Hovers continue to work
2929 window->consumeMotionEvent(
2930 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002931
2932 // Lift up the finger
2933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002934 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002935 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
2936 AINPUT_SOURCE_TOUCHSCREEN)
2937 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002938 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002939 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002940
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07002942 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002943 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
2944 AINPUT_SOURCE_STYLUS)
2945 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07002946 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002947 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002948 window->consumeMotionEvent(
2949 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08002950 window->assertNoEvents();
2951}
2952
2953/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07002954 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
2955 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
2956 *
2957 * Two windows: one on the left and one on the right.
2958 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
2959 * Stylus down on the left window, and then touch down on the right window.
2960 * Check that the right window doesn't get touches while the stylus is down on the left window.
2961 */
2962TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
2963 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2964 sp<FakeWindowHandle> leftWindow =
2965 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
2966 ADISPLAY_ID_DEFAULT);
2967 leftWindow->setFrame(Rect(0, 0, 100, 100));
2968
2969 sp<FakeWindowHandle> sbtRightWindow =
2970 sp<FakeWindowHandle>::make(application, mDispatcher,
2971 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
2972 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
2973 sbtRightWindow->setGlobalStylusBlocksTouch(true);
2974
2975 mDispatcher->onWindowInfosChanged(
2976 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
2977
2978 const int32_t stylusDeviceId = 5;
2979 const int32_t touchDeviceId = 4;
2980
2981 // Stylus down in the left window
2982 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2983 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
2984 .deviceId(stylusDeviceId)
2985 .build());
2986 leftWindow->consumeMotionEvent(
2987 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2988
2989 // Finger tap on the right window
2990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2991 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
2992 .deviceId(touchDeviceId)
2993 .build());
2994 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
2995 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
2996 .deviceId(touchDeviceId)
2997 .build());
2998
2999 // The touch should be blocked, because stylus is down somewhere else on screen!
3000 sbtRightWindow->assertNoEvents();
3001
3002 // Continue stylus motion, and ensure it's not impacted.
3003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3004 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3005 .deviceId(stylusDeviceId)
3006 .build());
3007 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3008 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3009 .deviceId(stylusDeviceId)
3010 .build());
3011 leftWindow->consumeMotionEvent(
3012 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3013 leftWindow->consumeMotionEvent(
3014 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3015
3016 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3017 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3018 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3019 .deviceId(touchDeviceId)
3020 .build());
3021 sbtRightWindow->consumeMotionEvent(
3022 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3023}
3024
3025/**
3026 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3027 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3028 *
3029 * Two windows: one on the left and one on the right.
3030 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3031 * Stylus hover on the left window, and then touch down on the right window.
3032 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3033 */
3034TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3035 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3036 sp<FakeWindowHandle> leftWindow =
3037 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
3038 ADISPLAY_ID_DEFAULT);
3039 leftWindow->setFrame(Rect(0, 0, 100, 100));
3040
3041 sp<FakeWindowHandle> sbtRightWindow =
3042 sp<FakeWindowHandle>::make(application, mDispatcher,
3043 "Stylus blocks touch (right) window", ADISPLAY_ID_DEFAULT);
3044 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3045 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3046
3047 mDispatcher->onWindowInfosChanged(
3048 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3049
3050 const int32_t stylusDeviceId = 5;
3051 const int32_t touchDeviceId = 4;
3052
3053 // Stylus hover in the left window
3054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3055 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3056 .deviceId(stylusDeviceId)
3057 .build());
3058 leftWindow->consumeMotionEvent(
3059 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3060
3061 // Finger tap on the right window
3062 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3063 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3064 .deviceId(touchDeviceId)
3065 .build());
3066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3067 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3068 .deviceId(touchDeviceId)
3069 .build());
3070
3071 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3072 sbtRightWindow->assertNoEvents();
3073
3074 // Continue stylus motion, and ensure it's not impacted.
3075 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3076 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3077 .deviceId(stylusDeviceId)
3078 .build());
3079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3080 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3081 .deviceId(stylusDeviceId)
3082 .build());
3083 leftWindow->consumeMotionEvent(
3084 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3085 leftWindow->consumeMotionEvent(
3086 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3087
3088 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3089 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3090 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3091 .deviceId(touchDeviceId)
3092 .build());
3093 sbtRightWindow->consumeMotionEvent(
3094 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3095}
3096
3097/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003098 * A spy window above a window with no input channel.
3099 * Start hovering with a stylus device, and then tap with it.
3100 * Ensure spy window receives the entire sequence.
3101 */
3102TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3103 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3104 sp<FakeWindowHandle> spyWindow =
3105 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3106 spyWindow->setFrame(Rect(0, 0, 200, 200));
3107 spyWindow->setTrustedOverlay(true);
3108 spyWindow->setSpy(true);
3109 sp<FakeWindowHandle> window =
3110 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3111 window->setNoInputChannel(true);
3112 window->setFrame(Rect(0, 0, 200, 200));
3113
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003114 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003116 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3118 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3119 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3121 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3123 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3124 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003125 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3126
3127 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003128 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3129 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3130 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003131 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3132
3133 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003134 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3135 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3136 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003137 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3138
3139 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003140 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3141 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3142 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003143 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3144 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003145 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3146 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3147 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003148 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3149
3150 // No more events
3151 spyWindow->assertNoEvents();
3152 window->assertNoEvents();
3153}
3154
3155/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003156 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3157 * rejected. But since we already have an ongoing gesture, this event should be processed.
3158 * This prevents inconsistent events being handled inside the dispatcher.
3159 */
3160TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3161 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3162
3163 sp<FakeWindowHandle> window =
3164 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3165 window->setFrame(Rect(0, 0, 200, 200));
3166
3167 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3168
3169 // Start hovering with stylus
3170 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3171 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3172 .build());
3173 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3174
3175 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3176 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3177 .build();
3178 // Make this 'hoverExit' event stale
3179 mFakePolicy->setStaleEventTimeout(100ms);
3180 std::this_thread::sleep_for(100ms);
3181
3182 // It shouldn't be dropped by the dispatcher, even though it's stale.
3183 mDispatcher->notifyMotion(hoverExit);
3184 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3185
3186 // Stylus starts hovering again! There should be no crash.
3187 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3188 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3189 .build());
3190 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3191}
3192
3193/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003194 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3195 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3196 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3197 * While the mouse is down, new move events from the touch device should be ignored.
3198 */
3199TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3200 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3201 sp<FakeWindowHandle> spyWindow =
3202 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3203 spyWindow->setFrame(Rect(0, 0, 200, 200));
3204 spyWindow->setTrustedOverlay(true);
3205 spyWindow->setSpy(true);
3206 sp<FakeWindowHandle> window =
3207 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3208 window->setFrame(Rect(0, 0, 200, 200));
3209
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003210 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003211
3212 const int32_t mouseDeviceId = 7;
3213 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003214
3215 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3217 .deviceId(mouseDeviceId)
3218 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3219 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003220 spyWindow->consumeMotionEvent(
3221 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3222 window->consumeMotionEvent(
3223 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3224
3225 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3227 .deviceId(touchDeviceId)
3228 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3229 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003230 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3231 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3232 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3233 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3234
Prabir Pradhan678438e2023-04-13 19:32:51 +00003235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3236 .deviceId(touchDeviceId)
3237 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3238 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003239 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3240 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3241
3242 // Pilfer the stream
3243 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3244 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3245
Prabir Pradhan678438e2023-04-13 19:32:51 +00003246 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3247 .deviceId(touchDeviceId)
3248 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3249 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003250 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3251
3252 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003253 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3254 .deviceId(mouseDeviceId)
3255 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3257 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003258
3259 spyWindow->consumeMotionEvent(
3260 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3261 spyWindow->consumeMotionEvent(
3262 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3263 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3264
Prabir Pradhan678438e2023-04-13 19:32:51 +00003265 mDispatcher->notifyMotion(
3266 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3267 .deviceId(mouseDeviceId)
3268 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3269 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3270 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3271 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003272 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3273 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3274
3275 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3277 .deviceId(mouseDeviceId)
3278 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3279 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3280 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003281 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3282 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3283
3284 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003285 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3286 .deviceId(touchDeviceId)
3287 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3288 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003289
3290 // No more events
3291 spyWindow->assertNoEvents();
3292 window->assertNoEvents();
3293}
3294
3295/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003296 * On the display, have a single window, and also an area where there's no window.
3297 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
3298 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
3299 */
3300TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
3301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3302 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003303 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003306
3307 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00003308 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003309
3310 mDispatcher->waitForIdle();
3311 window->assertNoEvents();
3312
3313 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003314 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003315 mDispatcher->waitForIdle();
3316 window->consumeMotionDown();
3317}
3318
3319/**
3320 * Same test as above, but instead of touching the empty space, the first touch goes to
3321 * non-touchable window.
3322 */
3323TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
3324 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3325 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003326 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003327 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3328 window1->setTouchable(false);
3329 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003330 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003331 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3332
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003333 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003334
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003335 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003336 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003337
3338 mDispatcher->waitForIdle();
3339 window1->assertNoEvents();
3340 window2->assertNoEvents();
3341
3342 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003343 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08003344 mDispatcher->waitForIdle();
3345 window2->consumeMotionDown();
3346}
3347
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003348/**
3349 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
3350 * to the event time of the first ACTION_DOWN sent to the particular window.
3351 */
3352TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
3353 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3354 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003355 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003356 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
3357 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003358 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003359 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
3360
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003361 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003362
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003363 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003364 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003365 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003366
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003367 const std::unique_ptr<MotionEvent> firstDown =
3368 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3369 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003370 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003371
3372 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00003373 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003374 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003375
3376 const std::unique_ptr<MotionEvent> secondDown =
3377 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
3378 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
3379 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
3380 // We currently send MOVE events to all windows receiving a split touch when there is any change
3381 // in the touch state, even when none of the pointers in the split window actually moved.
3382 // Document this behavior in the test.
3383 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003384
3385 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003386 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003387 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003388
3389 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3390 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003391
3392 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003393 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003394 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003395
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003396 window2->consumeMotionEvent(
3397 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
3398 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003399
3400 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003401 mDispatcher->notifyMotion(
3402 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003403 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003404
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003405 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
3406 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
3407
3408 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00003409 mDispatcher->notifyMotion(
3410 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003411 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00003412
3413 window1->consumeMotionEvent(
3414 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
3415 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00003416}
3417
Garfield Tandf26e862020-07-01 20:18:19 -07003418TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003419 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003420 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003421 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003422 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003423 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003424 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003425 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003426
3427 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3428
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003429 mDispatcher->onWindowInfosChanged(
3430 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003431
3432 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003434 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003435 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3436 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003437 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003438 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003439 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003440
3441 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003443 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003444 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3445 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003446 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003447 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003448 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3449 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003450
3451 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003453 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003454 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3455 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003456 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003457 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003458 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3459 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003460
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003461 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003462 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003463 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3464 AINPUT_SOURCE_MOUSE)
3465 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3466 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003467 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003468 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003469 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003470
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003471 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003472 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003473 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3474 AINPUT_SOURCE_MOUSE)
3475 .buttonState(0)
3476 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003477 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003478 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003479 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003480
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003482 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003483 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3484 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003485 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003486 .build()));
3487 windowLeft->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3488
3489 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003490 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003491 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003492 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3493 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003494 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003495 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003496 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003497
3498 // No more events
3499 windowLeft->assertNoEvents();
3500 windowRight->assertNoEvents();
3501}
3502
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003503/**
3504 * Put two fingers down (and don't release them) and click the mouse button.
3505 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
3506 * currently active gesture should be canceled, and the new one should proceed.
3507 */
3508TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
3509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3510 sp<FakeWindowHandle> window =
3511 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3512 window->setFrame(Rect(0, 0, 600, 800));
3513
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003514 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003515
3516 const int32_t touchDeviceId = 4;
3517 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003518
3519 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3521 .deviceId(touchDeviceId)
3522 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3523 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003524
Prabir Pradhan678438e2023-04-13 19:32:51 +00003525 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3526 .deviceId(touchDeviceId)
3527 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3528 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
3529 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003530 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3531 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3532
3533 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00003534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3535 .deviceId(mouseDeviceId)
3536 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3537 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3538 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003539 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
3540 WithPointerCount(2u)));
3541 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3542
Prabir Pradhan678438e2023-04-13 19:32:51 +00003543 mDispatcher->notifyMotion(
3544 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3545 .deviceId(mouseDeviceId)
3546 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3547 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3548 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3549 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003550 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3551
3552 // Try to send more touch events while the mouse is down. Since it's a continuation of an
3553 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3555 .deviceId(touchDeviceId)
3556 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
3557 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
3558 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003559 window->assertNoEvents();
3560}
3561
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003562TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
3563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3564
3565 sp<FakeWindowHandle> spyWindow =
3566 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3567 spyWindow->setFrame(Rect(0, 0, 600, 800));
3568 spyWindow->setTrustedOverlay(true);
3569 spyWindow->setSpy(true);
3570 sp<FakeWindowHandle> window =
3571 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3572 window->setFrame(Rect(0, 0, 600, 800));
3573
3574 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003575 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003576
3577 // Send mouse cursor to the window
3578 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003579 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003580 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3581 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003582 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003583 .build()));
3584
3585 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3586 WithSource(AINPUT_SOURCE_MOUSE)));
3587 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3588 WithSource(AINPUT_SOURCE_MOUSE)));
3589
3590 window->assertNoEvents();
3591 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003592}
3593
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003594TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
3595 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3596
3597 sp<FakeWindowHandle> spyWindow =
3598 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
3599 spyWindow->setFrame(Rect(0, 0, 600, 800));
3600 spyWindow->setTrustedOverlay(true);
3601 spyWindow->setSpy(true);
3602 sp<FakeWindowHandle> window =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3604 window->setFrame(Rect(0, 0, 600, 800));
3605
3606 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003607 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003608
3609 // Send mouse cursor to the window
3610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003611 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003612 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3613 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003615 .build()));
3616
3617 // Move mouse cursor
3618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003619 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003620 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3621 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003622 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003623 .build()));
3624
3625 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3626 WithSource(AINPUT_SOURCE_MOUSE)));
3627 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3628 WithSource(AINPUT_SOURCE_MOUSE)));
3629 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3630 WithSource(AINPUT_SOURCE_MOUSE)));
3631 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3632 WithSource(AINPUT_SOURCE_MOUSE)));
3633 // Touch down on the window
3634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003635 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003636 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3637 AINPUT_SOURCE_TOUCHSCREEN)
3638 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003639 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003640 .build()));
3641 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3642 WithSource(AINPUT_SOURCE_MOUSE)));
3643 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3644 WithSource(AINPUT_SOURCE_MOUSE)));
3645 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3646 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3647 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3648 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3649
3650 // pilfer the motion, retaining the gesture on the spy window.
3651 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3652 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
3653 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3654
3655 // Touch UP on the window
3656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003657 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003658 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3659 AINPUT_SOURCE_TOUCHSCREEN)
3660 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003661 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003662 .build()));
3663 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3664 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3665
3666 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
3667 // to send a new gesture. It should again go to both windows (spy and the window below), just
3668 // like the first gesture did, before pilfering. The window configuration has not changed.
3669
3670 // One more tap - DOWN
3671 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003672 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003673 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3674 AINPUT_SOURCE_TOUCHSCREEN)
3675 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003676 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003677 .build()));
3678 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3679 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3680 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3681 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3682
3683 // Touch UP on the window
3684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003685 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003686 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3687 AINPUT_SOURCE_TOUCHSCREEN)
3688 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003689 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08003690 .build()));
3691 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3692 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3693 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3694 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
3695
3696 window->assertNoEvents();
3697 spyWindow->assertNoEvents();
3698}
3699
Garfield Tandf26e862020-07-01 20:18:19 -07003700// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
3701// directly in this test.
3702TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07003703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tandf26e862020-07-01 20:18:19 -07003704 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003705 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07003706 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07003707
3708 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3709
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07003711
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003713 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003714 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3715 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003716 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003717 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003718 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07003719 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003720 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003721 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003722 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3723 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003724 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003725 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003726 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3727 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07003728
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003729 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003730 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003731 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
3732 AINPUT_SOURCE_MOUSE)
3733 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3734 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003735 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003736 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003737 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07003738
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003740 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003741 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
3742 AINPUT_SOURCE_MOUSE)
3743 .buttonState(0)
3744 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003745 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003746 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003747 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07003748
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003749 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003750 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003751 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
3752 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003753 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003754 .build()));
3755 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
3756
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07003757 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
3758 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
3759 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003760 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07003761 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
3762 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07003763 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07003764 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003765 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07003766}
3767
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003768/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003769 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
3770 * is generated.
3771 */
3772TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
3773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3774 sp<FakeWindowHandle> window =
3775 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3776 window->setFrame(Rect(0, 0, 1200, 800));
3777
3778 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3779
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003781
3782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003783 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003784 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3785 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003786 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003787 .build()));
3788 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3789
3790 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003791 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003792 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3793}
3794
3795/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07003796 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
3797 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00003798TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
3799 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
3800 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07003801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3802 sp<FakeWindowHandle> window =
3803 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3804 window->setFrame(Rect(0, 0, 1200, 800));
3805
3806 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3807
3808 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3809
3810 MotionEventBuilder hoverEnterBuilder =
3811 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3812 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
3813 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
3814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3815 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3817 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
3818 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3819 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3820}
3821
3822/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003823 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
3824 */
3825TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
3826 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3827 sp<FakeWindowHandle> window =
3828 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3829 window->setFrame(Rect(0, 0, 100, 100));
3830
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003831 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003832
3833 const int32_t mouseDeviceId = 7;
3834 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003835
3836 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00003837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3838 .deviceId(mouseDeviceId)
3839 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
3840 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003841 window->consumeMotionEvent(
3842 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3843
3844 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3846 .deviceId(touchDeviceId)
3847 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3848 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003849
3850 window->consumeMotionEvent(
3851 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
3852 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3853}
3854
3855/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003856 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003857 * The tap causes a HOVER_EXIT event to be generated because the current event
3858 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003859 */
3860TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
3861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3862 sp<FakeWindowHandle> window =
3863 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
3864 window->setFrame(Rect(0, 0, 100, 100));
3865
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003866 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
3868 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3869 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003870 ASSERT_NO_FATAL_FAILURE(
3871 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
3872 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003873
3874 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3876 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3877 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003878 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00003879 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
3880 WithSource(AINPUT_SOURCE_MOUSE))));
3881
3882 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003883 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
3884 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3885
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3887 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
3888 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08003889 ASSERT_NO_FATAL_FAILURE(
3890 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
3891 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
3892}
3893
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003894TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
3895 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3896 sp<FakeWindowHandle> windowDefaultDisplay =
3897 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
3898 ADISPLAY_ID_DEFAULT);
3899 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
3900 sp<FakeWindowHandle> windowSecondDisplay =
3901 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
3902 SECOND_DISPLAY_ID);
3903 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
3904
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003905 mDispatcher->onWindowInfosChanged(
3906 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003907
3908 // Set cursor position in window in default display and check that hover enter and move
3909 // events are generated.
3910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003911 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003912 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3913 AINPUT_SOURCE_MOUSE)
3914 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003915 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003916 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003917 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003918
3919 // Remove all windows in secondary display and check that no event happens on window in
3920 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003921 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
3922
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003923 windowDefaultDisplay->assertNoEvents();
3924
3925 // Move cursor position in window in default display and check that only hover move
3926 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003927 mDispatcher->onWindowInfosChanged(
3928 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003930 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003931 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3932 AINPUT_SOURCE_MOUSE)
3933 .displayId(ADISPLAY_ID_DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003934 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003935 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08003936 windowDefaultDisplay->consumeMotionEvent(
3937 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
3938 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02003939 windowDefaultDisplay->assertNoEvents();
3940}
3941
Garfield Tan00f511d2019-06-12 16:55:40 -07003942TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07003943 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07003944
3945 sp<FakeWindowHandle> windowLeft =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003946 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003947 windowLeft->setFrame(Rect(0, 0, 600, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003948 sp<FakeWindowHandle> windowRight =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003949 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003950 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07003951
3952 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
3953
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003954 mDispatcher->onWindowInfosChanged(
3955 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07003956
3957 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
3958 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08003959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003960 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07003961 ADISPLAY_ID_DEFAULT, {610, 400}, {599, 400}));
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08003962 windowLeft->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07003963 windowRight->assertNoEvents();
3964}
3965
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003966TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003967 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003968 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3969 "Fake Window", ADISPLAY_ID_DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07003970 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003971
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003972 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07003973 setFocusedWindow(window);
3974
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01003975 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003976
Prabir Pradhan678438e2023-04-13 19:32:51 +00003977 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003978
3979 // Window should receive key down event.
3980 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
3981
3982 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
3983 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003984 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00003985 window->consumeKeyUp(ADISPLAY_ID_DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003986}
3987
3988TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07003989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07003990 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
3991 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003992
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003993 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003994
Prabir Pradhan678438e2023-04-13 19:32:51 +00003995 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
3996 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08003997
3998 // Window should receive motion down event.
3999 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4000
4001 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4002 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004003 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004004 window->consumeMotionEvent(
4005 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004006}
4007
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004008TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4010 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4011 "Fake Window", ADISPLAY_ID_DEFAULT);
4012
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004013 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004014
4015 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4016 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
4017 .build());
4018
4019 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4020
4021 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
4022 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
4023 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4024
4025 // After the device has been reset, a new hovering stream can be sent to the window
4026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
4027 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
4028 .build());
4029 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
4030}
4031
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004032TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
4033 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004034 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4035 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004036 window->setFocusable(true);
4037
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004038 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004039 setFocusedWindow(window);
4040
4041 window->consumeFocusEvent(true);
4042
Prabir Pradhan678438e2023-04-13 19:32:51 +00004043 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004044 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
4045 const nsecs_t injectTime = keyArgs.eventTime;
4046 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00004047 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004048 // The dispatching time should be always greater than or equal to intercept key timeout.
4049 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4050 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
4051 std::chrono::nanoseconds(interceptKeyTimeout).count());
4052}
4053
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004054/**
4055 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
4056 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004057TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
4058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004059 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4060 "Fake Window", ADISPLAY_ID_DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004061 window->setFocusable(true);
4062
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004063 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004064 setFocusedWindow(window);
4065
4066 window->consumeFocusEvent(true);
4067
Prabir Pradhan678438e2023-04-13 19:32:51 +00004068 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004069 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07004070
4071 // Set a value that's significantly larger than the default consumption timeout. If the
4072 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
4073 mFakePolicy->setInterceptKeyTimeout(600ms);
4074 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
4075 // Window should receive key event immediately when same key up.
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08004076 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4077}
4078
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004079/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004080 * Two windows. First is a regular window. Second does not overlap with the first, and has
4081 * WATCH_OUTSIDE_TOUCH.
4082 * Both windows are owned by the same UID.
4083 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
4084 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
4085 */
4086TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
4087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004088 sp<FakeWindowHandle> window =
4089 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004090 window->setFrame(Rect{0, 0, 100, 100});
4091
4092 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004093 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004094 ADISPLAY_ID_DEFAULT);
4095 outsideWindow->setFrame(Rect{100, 100, 200, 200});
4096 outsideWindow->setWatchOutsideTouch(true);
4097 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004098 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004099
4100 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004101 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4102 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4103 {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004104 window->consumeMotionDown();
4105 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
4106 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
4107 outsideWindow->consumeMotionEvent(
4108 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00004109
4110 // Ensure outsideWindow doesn't get any more events for the gesture.
4111 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
4112 ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
4113 window->consumeMotionMove();
4114 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004115}
4116
4117/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004118 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
4119 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
4120 * ACTION_OUTSIDE event is sent per gesture.
4121 */
4122TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
4123 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
4124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004125 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4126 "First Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004127 window->setWatchOutsideTouch(true);
4128 window->setFrame(Rect{0, 0, 100, 100});
4129 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004130 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4131 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004132 secondWindow->setFrame(Rect{100, 100, 200, 200});
4133 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004134 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
4135 ADISPLAY_ID_DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004136 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004137 mDispatcher->onWindowInfosChanged(
4138 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004139
4140 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004141 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4142 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4143 {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004144 window->assertNoEvents();
4145 secondWindow->assertNoEvents();
4146
4147 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
4148 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004149 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4150 ADISPLAY_ID_DEFAULT,
4151 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08004152 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
4153 window->consumeMotionEvent(
4154 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004155 secondWindow->consumeMotionDown();
4156 thirdWindow->assertNoEvents();
4157
4158 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
4159 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004160 mDispatcher->notifyMotion(
4161 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4162 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004163 window->assertNoEvents();
4164 secondWindow->consumeMotionMove();
4165 thirdWindow->consumeMotionDown();
4166}
4167
Prabir Pradhan814fe082022-07-22 20:22:18 +00004168TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
4169 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004170 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4171 "Fake Window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004172 window->setFocusable(true);
4173
Patrick Williamsd828f302023-04-28 17:52:08 -05004174 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004175 setFocusedWindow(window);
4176
4177 window->consumeFocusEvent(true);
4178
Prabir Pradhan678438e2023-04-13 19:32:51 +00004179 const NotifyKeyArgs keyDown = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
4180 const NotifyKeyArgs keyUp = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
4181 mDispatcher->notifyKey(keyDown);
4182 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004183
4184 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
4185 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
4186
4187 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05004188 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00004189
4190 window->consumeFocusEvent(false);
4191
Prabir Pradhan678438e2023-04-13 19:32:51 +00004192 mDispatcher->notifyKey(keyDown);
4193 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00004194 window->assertNoEvents();
4195}
4196
Arthur Hung96483742022-11-15 03:30:48 +00004197TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
4198 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4199 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
4200 "Fake Window", ADISPLAY_ID_DEFAULT);
4201 // Ensure window is non-split and have some transform.
4202 window->setPreventSplitting(true);
4203 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05004204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00004205
4206 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004207 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung96483742022-11-15 03:30:48 +00004208 {50, 50}))
4209 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4210 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
4211
4212 const MotionEvent secondFingerDownEvent =
4213 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4214 .displayId(ADISPLAY_ID_DEFAULT)
4215 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004216 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4217 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00004218 .build();
4219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004220 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00004221 InputEventInjectionSync::WAIT_FOR_RESULT))
4222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4223
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004224 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
4225 ASSERT_NE(nullptr, event);
4226 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
4227 EXPECT_EQ(70, event->getX(0)); // 50 + 20
4228 EXPECT_EQ(90, event->getY(0)); // 50 + 40
4229 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
4230 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00004231}
4232
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07004233/**
4234 * Two windows: a splittable and a non-splittable.
4235 * The non-splittable window shouldn't receive any "incomplete" gestures.
4236 * Send the first pointer to the splittable window, and then touch the non-splittable window.
4237 * The second pointer should be dropped because the initial window is splittable, so it won't get
4238 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
4239 * "incomplete" gestures.
4240 */
4241TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
4242 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4243 sp<FakeWindowHandle> leftWindow =
4244 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
4245 ADISPLAY_ID_DEFAULT);
4246 leftWindow->setPreventSplitting(false);
4247 leftWindow->setFrame(Rect(0, 0, 100, 100));
4248 sp<FakeWindowHandle> rightWindow =
4249 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
4250 ADISPLAY_ID_DEFAULT);
4251 rightWindow->setPreventSplitting(true);
4252 rightWindow->setFrame(Rect(100, 100, 200, 200));
4253 mDispatcher->onWindowInfosChanged(
4254 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
4255
4256 // Touch down on left, splittable window
4257 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4258 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4259 .build());
4260 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4261
4262 mDispatcher->notifyMotion(
4263 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4264 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
4265 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
4266 .build());
4267 leftWindow->assertNoEvents();
4268 rightWindow->assertNoEvents();
4269}
4270
Harry Cuttsb166c002023-05-09 13:06:05 +00004271TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
4272 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4273 sp<FakeWindowHandle> window =
4274 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4275 window->setFrame(Rect(0, 0, 400, 400));
4276 sp<FakeWindowHandle> trustedOverlay =
4277 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
4278 ADISPLAY_ID_DEFAULT);
4279 trustedOverlay->setSpy(true);
4280 trustedOverlay->setTrustedOverlay(true);
4281
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004282 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004283
4284 // Start a three-finger touchpad swipe
4285 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4286 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4287 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4288 .build());
4289 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4290 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4291 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4292 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4293 .build());
4294 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4295 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4296 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4297 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4298 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4299 .build());
4300
4301 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4302 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4303 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
4304
4305 // Move the swipe a bit
4306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4307 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4308 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4309 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4310 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4311 .build());
4312
4313 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4314
4315 // End the swipe
4316 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4317 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4318 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4319 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4320 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4321 .build());
4322 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4323 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4324 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4325 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4326 .build());
4327 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4328 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4329 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4330 .build());
4331
4332 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
4333 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4334 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
4335
4336 window->assertNoEvents();
4337}
4338
4339TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
4340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4341 sp<FakeWindowHandle> window =
4342 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4343 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004344 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00004345
4346 // Start a three-finger touchpad swipe
4347 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4348 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4349 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4350 .build());
4351 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
4352 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4353 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4354 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4355 .build());
4356 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
4357 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
4358 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
4359 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
4360 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4361 .build());
4362
4363 // Move the swipe a bit
4364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4365 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4366 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4367 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4368 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4369 .build());
4370
4371 // End the swipe
4372 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
4373 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4374 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4375 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
4376 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4377 .build());
4378 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
4379 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4380 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
4381 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4382 .build());
4383 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
4384 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
4385 .classification(MotionClassification::MULTI_FINGER_SWIPE)
4386 .build());
4387
4388 window->assertNoEvents();
4389}
4390
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00004391/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004392 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
4393 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004394 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004395 */
4396TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
4397 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4398 sp<FakeWindowHandle> window =
4399 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4400 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004401 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004402
4403 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
4404 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4405 .downTime(baseTime + 10)
4406 .eventTime(baseTime + 10)
4407 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4408 .build());
4409
4410 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4411
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004412 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004413 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004414
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004415 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004416
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004417 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4418 .downTime(baseTime + 10)
4419 .eventTime(baseTime + 30)
4420 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4421 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4422 .build());
4423
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004424 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4425
4426 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004427 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4428 .downTime(baseTime + 10)
4429 .eventTime(baseTime + 40)
4430 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4431 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
4432 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004433
4434 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
4435
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4437 .downTime(baseTime + 10)
4438 .eventTime(baseTime + 50)
4439 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4440 .build());
4441
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00004442 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
4443
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4445 .downTime(baseTime + 60)
4446 .eventTime(baseTime + 60)
4447 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
4448 .build());
4449
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07004450 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07004451}
4452
4453/**
Hu Guo771a7692023-09-17 20:51:08 +08004454 * When there are multiple screens, such as screen projection to TV or screen recording, if the
4455 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
4456 * its coordinates should be converted by the transform of the windows of target screen.
4457 */
4458TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
4459 // This case will create a window and a spy window on the default display and mirror
4460 // window on the second display. cancel event is sent through spy window pilferPointers
4461 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4462
4463 sp<FakeWindowHandle> spyWindowDefaultDisplay =
4464 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
4465 spyWindowDefaultDisplay->setTrustedOverlay(true);
4466 spyWindowDefaultDisplay->setSpy(true);
4467
4468 sp<FakeWindowHandle> windowDefaultDisplay =
4469 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
4470 ADISPLAY_ID_DEFAULT);
4471 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
4472
4473 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
4474 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
4475
4476 // Add the windows to the dispatcher
4477 mDispatcher->onWindowInfosChanged(
4478 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
4479 *windowSecondDisplay->getInfo()},
4480 {},
4481 0,
4482 0});
4483
4484 // Send down to ADISPLAY_ID_DEFAULT
4485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4486 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4487 {100, 100}))
4488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
4489
4490 spyWindowDefaultDisplay->consumeMotionDown();
4491 windowDefaultDisplay->consumeMotionDown();
4492
4493 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
4494
4495 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004496 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
4497 ASSERT_NE(nullptr, event);
4498 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08004499
4500 // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
4501 // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
4502 // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
4503 // SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004504 EXPECT_EQ(100, event->getX(0));
4505 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08004506}
4507
4508/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004509 * Ensure the correct coordinate spaces are used by InputDispatcher.
4510 *
4511 * InputDispatcher works in the display space, so its coordinate system is relative to the display
4512 * panel. Windows get events in the window space, and get raw coordinates in the logical display
4513 * space.
4514 */
4515class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
4516public:
4517 void SetUp() override {
4518 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004519 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004520 }
4521
4522 void addDisplayInfo(int displayId, const ui::Transform& transform) {
4523 gui::DisplayInfo info;
4524 info.displayId = displayId;
4525 info.transform = transform;
4526 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05004527 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004528 }
4529
4530 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
4531 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05004532 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004533 }
4534
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004535 void removeAllWindowsAndDisplays() {
4536 mDisplayInfos.clear();
4537 mWindowInfos.clear();
4538 }
4539
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004540 // Set up a test scenario where the display has a scaled projection and there are two windows
4541 // on the display.
4542 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
4543 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
4544 // respectively.
4545 ui::Transform displayTransform;
4546 displayTransform.set(2, 0, 0, 4);
4547 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4548
4549 std::shared_ptr<FakeApplicationHandle> application =
4550 std::make_shared<FakeApplicationHandle>();
4551
4552 // Add two windows to the display. Their frames are represented in the display space.
4553 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004554 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4555 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004556 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
4557 addWindow(firstWindow);
4558
4559 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004560 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4561 ADISPLAY_ID_DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004562 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
4563 addWindow(secondWindow);
4564 return {std::move(firstWindow), std::move(secondWindow)};
4565 }
4566
4567private:
4568 std::vector<gui::DisplayInfo> mDisplayInfos;
4569 std::vector<gui::WindowInfo> mWindowInfos;
4570};
4571
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004572TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004573 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4574 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004575 // selected so that if the hit test was performed with the point and the bounds being in
4576 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004577 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4578 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4579 {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004580
4581 firstWindow->consumeMotionDown();
4582 secondWindow->assertNoEvents();
4583}
4584
4585// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
4586// the event should be treated as being in the logical display space.
4587TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
4588 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4589 // Send down to the first window. The point is represented in the logical display space. The
4590 // point is selected so that if the hit test was done in logical display space, then it would
4591 // end up in the incorrect window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004592 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004593 PointF{75 * 2, 55 * 4});
4594
4595 firstWindow->consumeMotionDown();
4596 secondWindow->assertNoEvents();
4597}
4598
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004599// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
4600// event should be treated as being in the logical display space.
4601TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
4602 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4603
4604 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4605 ui::Transform injectedEventTransform;
4606 injectedEventTransform.set(matrix);
4607 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
4608 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
4609
4610 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4611 .displayId(ADISPLAY_ID_DEFAULT)
4612 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004613 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004614 .x(untransformedPoint.x)
4615 .y(untransformedPoint.y))
4616 .build();
4617 event.transform(matrix);
4618
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004619 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00004620 InputEventInjectionSync::WAIT_FOR_RESULT);
4621
4622 firstWindow->consumeMotionDown();
4623 secondWindow->assertNoEvents();
4624}
4625
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004626TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
4627 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4628
4629 // Send down to the second window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004630 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4631 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4632 {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004633
4634 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004635 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
4636 ASSERT_NE(nullptr, event);
4637 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004638
4639 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004640 EXPECT_EQ(300, event->getRawX(0));
4641 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004642
4643 // Ensure that the x and y values are in the window's coordinate space.
4644 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
4645 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08004646 EXPECT_EQ(100, event->getX(0));
4647 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07004648}
4649
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004650TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
4651 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4652 // The monitor will always receive events in the logical display's coordinate space, because
4653 // it does not have a window.
Prabir Pradhanfb549072023-10-05 19:17:36 +00004654 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ADISPLAY_ID_DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00004655
4656 // Send down to the first window.
4657 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4658 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4659 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4660 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4661
4662 // Second pointer goes down on second window.
4663 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4664 ADISPLAY_ID_DEFAULT,
4665 {PointF{50, 100}, PointF{150, 220}}));
4666 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
4667 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
4668 {1, PointF{300, 880}}};
4669 monitor.consumeMotionEvent(
4670 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
4671
4672 mDispatcher->cancelCurrentTouch();
4673
4674 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4675 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
4676 monitor.consumeMotionEvent(
4677 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
4678}
4679
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004680TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
4681 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4682
4683 // Send down to the first window.
4684 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
4685 ADISPLAY_ID_DEFAULT, {PointF{50, 100}}));
4686 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
4687
4688 // The pointer is transferred to the second window, and the second window receives it in the
4689 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00004690 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00004691 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
4692 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
4693}
4694
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004695TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
4696 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4697
4698 // Send hover move to the second window, and ensure it shows up as hover enter.
4699 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4700 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4701 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4702 WithCoords(100, 80), WithRawCoords(300, 880)));
4703
4704 // Touch down at the same location and ensure a hover exit is synthesized.
4705 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4706 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4707 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4708 WithRawCoords(300, 880)));
4709 secondWindow->consumeMotionEvent(
4710 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4711 secondWindow->assertNoEvents();
4712 firstWindow->assertNoEvents();
4713}
4714
Prabir Pradhan453ae732023-10-13 14:30:14 +00004715// Same as above, but while the window is being mirrored.
4716TEST_F(InputDispatcherDisplayProjectionTest,
4717 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
4718 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4719
4720 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4721 ui::Transform secondDisplayTransform;
4722 secondDisplayTransform.set(matrix);
4723 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4724
4725 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4726 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4727 addWindow(secondWindowClone);
4728
4729 // Send hover move to the second window, and ensure it shows up as hover enter.
4730 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
4731 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4732 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4733 WithCoords(100, 80), WithRawCoords(300, 880)));
4734
4735 // Touch down at the same location and ensure a hover exit is synthesized for the correct
4736 // display.
4737 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
4738 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4739 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4740 WithRawCoords(300, 880)));
4741 secondWindow->consumeMotionEvent(
4742 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
4743 secondWindow->assertNoEvents();
4744 firstWindow->assertNoEvents();
4745}
4746
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00004747TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
4748 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4749
4750 // Send hover enter to second window
4751 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4752 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4753 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4754 WithCoords(100, 80), WithRawCoords(300, 880)));
4755
4756 mDispatcher->cancelCurrentTouch();
4757
4758 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4759 WithRawCoords(300, 880)));
4760 secondWindow->assertNoEvents();
4761 firstWindow->assertNoEvents();
4762}
4763
Prabir Pradhan453ae732023-10-13 14:30:14 +00004764// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00004765TEST_F(InputDispatcherDisplayProjectionTest,
4766 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
4767 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
4768
4769 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
4770 ui::Transform secondDisplayTransform;
4771 secondDisplayTransform.set(matrix);
4772 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
4773
4774 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
4775 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
4776 addWindow(secondWindowClone);
4777
4778 // Send hover enter to second window
4779 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
4780 ADISPLAY_ID_DEFAULT, {PointF{150, 220}}));
4781 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
4782 WithCoords(100, 80), WithRawCoords(300, 880),
4783 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4784
4785 mDispatcher->cancelCurrentTouch();
4786
4787 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
4788 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
4789 WithRawCoords(300, 880),
4790 WithDisplayId(ADISPLAY_ID_DEFAULT)));
4791 secondWindow->assertNoEvents();
4792 firstWindow->assertNoEvents();
4793}
4794
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004795/** Ensure consistent behavior of InputDispatcher in all orientations. */
4796class InputDispatcherDisplayOrientationFixture
4797 : public InputDispatcherDisplayProjectionTest,
4798 public ::testing::WithParamInterface<ui::Rotation> {};
4799
4800// This test verifies the touchable region of a window for all rotations of the display by tapping
4801// in different locations on the display, specifically points close to the four corners of a
4802// window.
4803TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
4804 constexpr static int32_t displayWidth = 400;
4805 constexpr static int32_t displayHeight = 800;
4806
4807 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4808
4809 const auto rotation = GetParam();
4810
4811 // Set up the display with the specified rotation.
4812 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4813 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4814 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4815 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4816 logicalDisplayWidth, logicalDisplayHeight);
4817 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4818
4819 // Create a window with its bounds determined in the logical display.
4820 const Rect frameInLogicalDisplay(100, 100, 200, 300);
4821 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
4822 sp<FakeWindowHandle> window =
4823 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
4824 window->setFrame(frameInDisplay, displayTransform);
4825 addWindow(window);
4826
4827 // The following points in logical display space should be inside the window.
4828 static const std::array<vec2, 4> insidePoints{
4829 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4830 for (const auto pointInsideWindow : insidePoints) {
4831 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
4832 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004833 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4834 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4835 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004836 window->consumeMotionDown();
4837
Prabir Pradhan678438e2023-04-13 19:32:51 +00004838 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4839 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4840 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004841 window->consumeMotionUp();
4842 }
4843
4844 // The following points in logical display space should be outside the window.
4845 static const std::array<vec2, 5> outsidePoints{
4846 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4847 for (const auto pointOutsideWindow : outsidePoints) {
4848 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
4849 const PointF pointInDisplaySpace{p.x, p.y};
Prabir Pradhan678438e2023-04-13 19:32:51 +00004850 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4851 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4852 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004853
Prabir Pradhan678438e2023-04-13 19:32:51 +00004854 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4855 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4856 {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004857 }
4858 window->assertNoEvents();
4859}
4860
Linnan Li5e5645e2024-03-05 14:43:05 +00004861// This test verifies the occlusion detection for all rotations of the display by tapping
4862// in different locations on the display, specifically points close to the four corners of a
4863// window.
4864TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
4865 constexpr static int32_t displayWidth = 400;
4866 constexpr static int32_t displayHeight = 800;
4867
4868 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
4869 std::make_shared<FakeApplicationHandle>();
4870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4871
4872 const auto rotation = GetParam();
4873
4874 // Set up the display with the specified rotation.
4875 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
4876 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
4877 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
4878 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
4879 logicalDisplayWidth, logicalDisplayHeight);
4880 addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform);
4881
4882 // Create a window that not trusted.
4883 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
4884
4885 const Rect untrustedWindowFrameInDisplay =
4886 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
4887
4888 sp<FakeWindowHandle> untrustedWindow =
4889 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
4890 ADISPLAY_ID_DEFAULT);
4891 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
4892 untrustedWindow->setTrustedOverlay(false);
4893 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
4894 untrustedWindow->setTouchable(false);
4895 untrustedWindow->setAlpha(1.0f);
4896 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
4897 addWindow(untrustedWindow);
4898
4899 // Create a simple app window below the untrusted window.
4900 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
4901 const Rect simpleAppWindowFrameInDisplay =
4902 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
4903
4904 sp<FakeWindowHandle> simpleAppWindow =
4905 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
4906 ADISPLAY_ID_DEFAULT);
4907 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
4908 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
4909 addWindow(simpleAppWindow);
4910
4911 // The following points in logical display space should be inside the untrusted window, so
4912 // the simple window could not receive events that coordinate is these point.
4913 static const std::array<vec2, 4> untrustedPoints{
4914 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
4915
4916 for (const auto untrustedPoint : untrustedPoints) {
4917 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
4918 const PointF pointInDisplaySpace{p.x, p.y};
4919 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4920 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4921 {pointInDisplaySpace}));
4922 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4923 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4924 {pointInDisplaySpace}));
4925 }
4926 untrustedWindow->assertNoEvents();
4927 simpleAppWindow->assertNoEvents();
4928 // The following points in logical display space should be outside the untrusted window, so
4929 // the simple window should receive events that coordinate is these point.
4930 static const std::array<vec2, 5> trustedPoints{
4931 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
4932 for (const auto trustedPoint : trustedPoints) {
4933 const vec2 p = displayTransform.inverse().transform(trustedPoint);
4934 const PointF pointInDisplaySpace{p.x, p.y};
4935 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4936 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4937 {pointInDisplaySpace}));
4938 simpleAppWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
4939 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
4940 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP,
4941 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
4942 {pointInDisplaySpace}));
4943 simpleAppWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT,
4944 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
4945 }
4946 untrustedWindow->assertNoEvents();
4947}
4948
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00004949// Run the precision tests for all rotations.
4950INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
4951 InputDispatcherDisplayOrientationFixture,
4952 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
4953 ui::ROTATION_270),
4954 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
4955 return ftl::enum_string(testParamInfo.param);
4956 });
4957
Siarhei Vishniakou18050092021-09-01 13:32:49 -07004958using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
4959 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004960
4961class TransferTouchFixture : public InputDispatcherTest,
4962 public ::testing::WithParamInterface<TransferFunction> {};
4963
4964TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07004965 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08004966
4967 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004968 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004969 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
4970 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004971 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10004972 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004973 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
4974 ADISPLAY_ID_DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00004975 sp<FakeWindowHandle> wallpaper =
4976 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper", ADISPLAY_ID_DEFAULT);
4977 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00004978 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004979 mDispatcher->onWindowInfosChanged(
4980 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00004981 setFocusedWindow(firstWindow);
4982 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004983
4984 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004985 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
4986 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00004987
Svet Ganov5d3bc372020-01-26 23:11:07 -08004988 // Only the first window should get the down event
4989 firstWindow->consumeMotionDown();
4990 secondWindow->assertNoEvents();
Arthur Hungc539dbb2022-12-08 07:45:36 +00004991 wallpaper->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00004992 // Dispatcher reports pointer down outside focus for the wallpaper
4993 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08004994
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00004995 // Transfer touch to the second window
4996 TransferFunction f = GetParam();
4997 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
4998 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08004999 // The first window gets cancel and the second gets down
5000 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005001 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005002 wallpaper->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005003 // There should not be any changes to the focused window when transferring touch
5004 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005005
5006 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005007 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5008 ADISPLAY_ID_DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00005009 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08005010 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005011 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005012 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005013}
5014
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005015/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00005016 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
5017 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
5018 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005019 * natural to the user.
5020 * In this test, we are sending a pointer to both spy window and first window. We then try to
5021 * transfer touch to the second window. The dispatcher should identify the first window as the
5022 * one that should lose the gesture, and therefore the action should be to move the gesture from
5023 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005024 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
5025 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005026 */
5027TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
5028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5029
5030 // Create a couple of windows + a spy window
5031 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005032 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005033 spyWindow->setTrustedOverlay(true);
5034 spyWindow->setSpy(true);
5035 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005036 sp<FakeWindowHandle>::make(application, mDispatcher, "First", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005037 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005038 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005039
5040 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005041 mDispatcher->onWindowInfosChanged(
5042 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005043
5044 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005045 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5046 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005047 // Only the first window and spy should get the down event
5048 spyWindow->consumeMotionDown();
5049 firstWindow->consumeMotionDown();
5050
5051 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00005052 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005053 TransferFunction f = GetParam();
5054 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5055 ASSERT_TRUE(success);
5056 // The first window gets cancel and the second gets down
5057 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005058 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005059
5060 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005061 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5062 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005063 // The first window gets no events and the second+spy get up
5064 firstWindow->assertNoEvents();
5065 spyWindow->consumeMotionUp();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005066 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005067}
5068
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005069TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005070 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005071
5072 PointF touchPoint = {10, 10};
5073
5074 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005075 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005076 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5077 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005078 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005079 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005080 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5081 ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08005082 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005083
5084 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005085 mDispatcher->onWindowInfosChanged(
5086 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005087
5088 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005089 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5090 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5091 {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005092 // Only the first window should get the down event
5093 firstWindow->consumeMotionDown();
5094 secondWindow->assertNoEvents();
5095
5096 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005097 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5098 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005099 // Only the first window should get the pointer down event
5100 firstWindow->consumeMotionPointerDown(1);
5101 secondWindow->assertNoEvents();
5102
5103 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005104 TransferFunction f = GetParam();
5105 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5106 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005107 // The first window gets cancel and the second gets down and pointer down
5108 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005109 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
5110 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5111 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005112
5113 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005114 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5115 ADISPLAY_ID_DEFAULT, {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005116 // The first window gets nothing and the second gets pointer up
5117 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005118 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5119 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005120
5121 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005122 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5123 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005124 // The first window gets nothing and the second gets up
5125 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005126 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005127}
5128
Arthur Hungc539dbb2022-12-08 07:45:36 +00005129TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
5130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5131
5132 // Create a couple of windows
5133 sp<FakeWindowHandle> firstWindow =
5134 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5135 ADISPLAY_ID_DEFAULT);
5136 firstWindow->setDupTouchToWallpaper(true);
5137 sp<FakeWindowHandle> secondWindow =
5138 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5139 ADISPLAY_ID_DEFAULT);
5140 secondWindow->setDupTouchToWallpaper(true);
5141
5142 sp<FakeWindowHandle> wallpaper1 =
5143 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1", ADISPLAY_ID_DEFAULT);
5144 wallpaper1->setIsWallpaper(true);
5145
5146 sp<FakeWindowHandle> wallpaper2 =
5147 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2", ADISPLAY_ID_DEFAULT);
5148 wallpaper2->setIsWallpaper(true);
5149 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005150 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
5151 *secondWindow->getInfo(), *wallpaper2->getInfo()},
5152 {},
5153 0,
5154 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00005155
5156 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005157 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5158 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005159
5160 // Only the first window should get the down event
5161 firstWindow->consumeMotionDown();
5162 secondWindow->assertNoEvents();
5163 wallpaper1->consumeMotionDown(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
5164 wallpaper2->assertNoEvents();
5165
5166 // Transfer touch focus to the second window
5167 TransferFunction f = GetParam();
5168 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
5169 ASSERT_TRUE(success);
5170
5171 // The first window gets cancel and the second gets down
5172 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005173 secondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005174 wallpaper1->consumeMotionCancel(ADISPLAY_ID_DEFAULT, expectedWallpaperFlags);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005175 wallpaper2->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5176 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005177
5178 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005179 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5180 ADISPLAY_ID_DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00005181 // The first window gets no events and the second gets up
5182 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005183 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005184 wallpaper1->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005185 wallpaper2->consumeMotionUp(ADISPLAY_ID_DEFAULT,
5186 expectedWallpaperFlags | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00005187}
5188
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005189// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00005190// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005191// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005192INSTANTIATE_TEST_SUITE_P(
5193 InputDispatcherTransferFunctionTests, TransferTouchFixture,
5194 ::testing::Values(
5195 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
5196 sp<IBinder> destChannelToken) {
5197 return dispatcher->transferTouchOnDisplay(destChannelToken,
5198 ADISPLAY_ID_DEFAULT);
5199 },
5200 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
5201 sp<IBinder> to) {
5202 return dispatcher->transferTouchGesture(from, to,
5203 /*isDragAndDrop=*/false);
5204 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005205
Prabir Pradhan367f3432024-02-13 23:05:58 +00005206TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07005207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08005208
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005209 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005210 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5211 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005212 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005213
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10005214 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005215 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5216 ADISPLAY_ID_DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005217 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005218
5219 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005220 mDispatcher->onWindowInfosChanged(
5221 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08005222
5223 PointF pointInFirst = {300, 200};
5224 PointF pointInSecond = {300, 600};
5225
5226 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005227 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5228 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5229 {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005230 // Only the first window should get the down event
5231 firstWindow->consumeMotionDown();
5232 secondWindow->assertNoEvents();
5233
5234 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005235 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5236 ADISPLAY_ID_DEFAULT,
5237 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005238 // The first window gets a move and the second a down
5239 firstWindow->consumeMotionMove();
5240 secondWindow->consumeMotionDown();
5241
Prabir Pradhan367f3432024-02-13 23:05:58 +00005242 // Transfer touch to the second window
5243 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08005244 // The first window gets cancel and the new gets pointer down (it already saw down)
5245 firstWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005246 secondWindow->consumeMotionPointerDown(1, ADISPLAY_ID_DEFAULT,
5247 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005248
5249 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005250 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5251 ADISPLAY_ID_DEFAULT,
5252 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005253 // The first window gets nothing and the second gets pointer up
5254 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005255 secondWindow->consumeMotionPointerUp(1, ADISPLAY_ID_DEFAULT,
5256 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005257
5258 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005259 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5260 ADISPLAY_ID_DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08005261 // The first window gets nothing and the second gets up
5262 firstWindow->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005263 secondWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08005264}
5265
Prabir Pradhan367f3432024-02-13 23:05:58 +00005266// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
5267// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
5268// receiving touch is not supported, so the touch should continue on those windows and the
5269// transferred-to window should get nothing.
5270TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005271 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5272
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005273 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005274 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5275 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005276 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005277
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005278 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005279 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5280 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005281 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005282
5283 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005284 mDispatcher->onWindowInfosChanged(
5285 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005286
5287 PointF pointInFirst = {300, 200};
5288 PointF pointInSecond = {300, 600};
5289
5290 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005291 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5292 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5293 {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005294 // Only the first window should get the down event
5295 firstWindow->consumeMotionDown();
5296 secondWindow->assertNoEvents();
5297
5298 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005299 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5300 ADISPLAY_ID_DEFAULT,
5301 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005302 // The first window gets a move and the second a down
5303 firstWindow->consumeMotionMove();
5304 secondWindow->consumeMotionDown();
5305
5306 // Transfer touch focus to the second window
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07005307 const bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +00005308 mDispatcher->transferTouchOnDisplay(secondWindow->getToken(), ADISPLAY_ID_DEFAULT);
5309 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005310 ASSERT_FALSE(transferred);
5311 firstWindow->assertNoEvents();
5312 secondWindow->assertNoEvents();
5313
5314 // The rest of the dispatch should proceed as normal
5315 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005316 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
5317 ADISPLAY_ID_DEFAULT,
5318 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005319 // The first window gets MOVE and the second gets pointer up
5320 firstWindow->consumeMotionMove();
5321 secondWindow->consumeMotionUp();
5322
5323 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005324 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5325 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00005326 // The first window gets nothing and the second gets up
5327 firstWindow->consumeMotionUp();
5328 secondWindow->assertNoEvents();
5329}
5330
Arthur Hungabbb9d82021-09-01 14:52:30 +00005331// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00005332// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00005333// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005334TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005335 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5336 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005337 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005338 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005339 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005340 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005341 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005342
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005343 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005344 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005345
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005346 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005347 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005348
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005349 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005350 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005351
5352 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005353 mDispatcher->onWindowInfosChanged(
5354 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5355 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5356 *secondWindowInPrimary->getInfo()},
5357 {},
5358 0,
5359 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005360
5361 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005362 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005363 {50, 50}))
5364 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5365
5366 // Window should receive motion event.
5367 firstWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5368
Prabir Pradhan367f3432024-02-13 23:05:58 +00005369 // Transfer touch
5370 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
5371 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005372 // The first window gets cancel.
5373 firstWindowInPrimary->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005374 secondWindowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT,
5375 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005376
5377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005378 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005379 ADISPLAY_ID_DEFAULT, {150, 50}))
5380 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5381 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005382 secondWindowInPrimary->consumeMotionMove(ADISPLAY_ID_DEFAULT,
5383 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005384
5385 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005386 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005387 {150, 50}))
5388 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5389 firstWindowInPrimary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005390 secondWindowInPrimary->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005391}
5392
Prabir Pradhan367f3432024-02-13 23:05:58 +00005393// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
5394// 'transferTouchOnDisplay' api.
5395TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00005396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5397 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005398 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005399 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005400 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005401 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005402 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005403
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005404 sp<FakeWindowHandle> mirrorWindowInPrimary = firstWindowInPrimary->clone(ADISPLAY_ID_DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005405 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005406
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005407 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005408 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005409
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005410 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005411 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005412
5413 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005414 mDispatcher->onWindowInfosChanged(
5415 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
5416 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
5417 *secondWindowInPrimary->getInfo()},
5418 {},
5419 0,
5420 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00005421
5422 // Touch on second display.
5423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005424 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5425 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5427
5428 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005429 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005430
5431 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00005432 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
5433 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00005434
5435 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005436 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00005437 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
5438 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005439
5440 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005441 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00005442 SECOND_DISPLAY_ID, {150, 50}))
5443 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005444 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005445 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
5446 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005447
5448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005449 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00005450 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00005451 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00005452 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00005453}
5454
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005455TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005457 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5458 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005459
Vishnu Nair47074b82020-08-14 11:54:47 -07005460 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005461 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005462 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005463
5464 window->consumeFocusEvent(true);
5465
Prabir Pradhan678438e2023-04-13 19:32:51 +00005466 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005467
5468 // Window should receive key down event.
5469 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00005470
5471 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005472 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005473 mFakePolicy->assertUserActivityPoked();
5474}
5475
5476TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
5477 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5478 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5479 "Fake Window", ADISPLAY_ID_DEFAULT);
5480
5481 window->setDisableUserActivity(true);
5482 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005483 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005484 setFocusedWindow(window);
5485
5486 window->consumeFocusEvent(true);
5487
5488 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5489
5490 // Window should receive key down event.
5491 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
5492
5493 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005494 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00005495 mFakePolicy->assertUserActivityNotPoked();
5496}
5497
5498TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
5499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5500 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5501 "Fake Window", ADISPLAY_ID_DEFAULT);
5502
5503 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005504 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005505 setFocusedWindow(window);
5506
5507 window->consumeFocusEvent(true);
5508
5509 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5510 mDispatcher->waitForIdle();
5511
5512 // System key is not passed down
5513 window->assertNoEvents();
5514
5515 // Should have poked user activity
5516 mFakePolicy->assertUserActivityPoked();
5517}
5518
5519TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
5520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5521 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5522 "Fake Window", ADISPLAY_ID_DEFAULT);
5523
5524 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005525 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005526 setFocusedWindow(window);
5527
5528 window->consumeFocusEvent(true);
5529
5530 mDispatcher->notifyKey(generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5531 mDispatcher->waitForIdle();
5532
5533 // System key is not passed down
5534 window->assertNoEvents();
5535
5536 // Should have poked user activity
5537 mFakePolicy->assertUserActivityPoked();
5538}
5539
5540TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
5541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5542 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5543 "Fake Window", ADISPLAY_ID_DEFAULT);
5544
5545 window->setDisableUserActivity(true);
5546 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005547 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00005548 setFocusedWindow(window);
5549
5550 window->consumeFocusEvent(true);
5551
5552 mDispatcher->notifyKey(generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
5553 mDispatcher->waitForIdle();
5554
5555 // System key is not passed down
5556 window->assertNoEvents();
5557
5558 // Should have poked user activity
5559 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005560}
5561
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005562TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
5563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5564 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5565 "Fake Window", ADISPLAY_ID_DEFAULT);
5566
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005567 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005568
5569 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005570 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005571 ADISPLAY_ID_DEFAULT, {100, 100}))
5572 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5573
5574 window->consumeMotionEvent(
5575 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
5576
5577 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00005578 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07005579 mFakePolicy->assertUserActivityPoked();
5580}
5581
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005582TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07005583 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005584 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5585 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005586
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005587 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005588
Prabir Pradhan678438e2023-04-13 19:32:51 +00005589 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005590 mDispatcher->waitForIdle();
5591
5592 window->assertNoEvents();
5593}
5594
5595// If a window is touchable, but does not have focus, it should receive motion events, but not keys
5596TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07005597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005598 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5599 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005600
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005601 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005602
5603 // Send key
Prabir Pradhan678438e2023-04-13 19:32:51 +00005604 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005605 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00005606 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5607 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005608
5609 // Window should receive only the motion event
5610 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5611 window->assertNoEvents(); // Key event or focus event will not be received
5612}
5613
arthurhungea3f4fc2020-12-21 23:18:53 +08005614TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
5615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5616
arthurhungea3f4fc2020-12-21 23:18:53 +08005617 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005618 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5619 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005620 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08005621
arthurhungea3f4fc2020-12-21 23:18:53 +08005622 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005623 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
5624 ADISPLAY_ID_DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08005625 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08005626
5627 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005628 mDispatcher->onWindowInfosChanged(
5629 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08005630
5631 PointF pointInFirst = {300, 200};
5632 PointF pointInSecond = {300, 600};
5633
5634 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005635 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
5636 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5637 {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005638 // Only the first window should get the down event
5639 firstWindow->consumeMotionDown();
5640 secondWindow->assertNoEvents();
5641
5642 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00005643 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5644 ADISPLAY_ID_DEFAULT,
5645 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08005646 // The first window gets a move and the second a down
5647 firstWindow->consumeMotionMove();
5648 secondWindow->consumeMotionDown();
5649
5650 // Send pointer cancel to the second window
5651 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08005652 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungea3f4fc2020-12-21 23:18:53 +08005653 {pointInFirst, pointInSecond});
5654 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00005655 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08005656 // The first window gets move and the second gets cancel.
5657 firstWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5658 secondWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
5659
5660 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005661 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5662 ADISPLAY_ID_DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08005663 // The first window gets up and the second gets nothing.
5664 firstWindow->consumeMotionUp();
5665 secondWindow->assertNoEvents();
5666}
5667
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005668TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
5669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5670
5671 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005672 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005673 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005674 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
5675 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
5676 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
5677
Harry Cutts33476232023-01-30 19:57:29 +00005678 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00005679 window->assertNoEvents();
5680 mDispatcher->waitForIdle();
5681}
5682
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005683using InputDispatcherMonitorTest = InputDispatcherTest;
5684
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005685/**
5686 * Two entities that receive touch: A window, and a global monitor.
5687 * The touch goes to the window, and then the window disappears.
5688 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
5689 * for the monitor, as well.
5690 * 1. foregroundWindow
5691 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
5692 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005693TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005694 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5695 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005696 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005697
Prabir Pradhanfb549072023-10-05 19:17:36 +00005698 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005699
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005700 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005703 {100, 200}))
5704 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5705
5706 // Both the foreground window and the global monitor should receive the touch down
5707 window->consumeMotionDown();
5708 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
5709
5710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005711 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005712 ADISPLAY_ID_DEFAULT, {110, 200}))
5713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5714
5715 window->consumeMotionMove();
5716 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5717
5718 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005719 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005720 window->consumeMotionCancel();
5721 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
5722
5723 // If more events come in, there will be no more foreground window to send them to. This will
5724 // cause a cancel for the monitor, as well.
5725 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005726 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00005727 ADISPLAY_ID_DEFAULT, {120, 200}))
5728 << "Injection should fail because the window was removed";
5729 window->assertNoEvents();
5730 // Global monitor now gets the cancel
5731 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
5732}
5733
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005734TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07005735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005736 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5737 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005739
Prabir Pradhanfb549072023-10-05 19:17:36 +00005740 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005741
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005743 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005744 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Michael Wright3a240c42019-12-10 20:53:41 +00005745 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08005746 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005747}
5748
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005749TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Prabir Pradhanfb549072023-10-05 19:17:36 +00005750 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005751
Chris Yea209fde2020-07-22 13:54:51 -07005752 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005753 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5754 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00005756
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
chaviwd1c23182019-12-20 18:44:56 -08005760 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005761 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005762
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005763 // Pilfer pointers from the monitor.
5764 // This should not do anything and the window should continue to receive events.
5765 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00005766
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005768 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005769 ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005771
5772 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
5773 window->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00005774}
5775
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005776TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07005777 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005778 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
5779 "Fake Window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005780 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07005781 window->setWindowOffset(20, 40);
5782 window->setWindowTransform(0, 1, -1, 0);
5783
Prabir Pradhanfb549072023-10-05 19:17:36 +00005784 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07005785
5786 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005787 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07005788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5789 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005790 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
5791 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07005792 // Even though window has transform, gesture monitor must not.
5793 ASSERT_EQ(ui::Transform(), event->getTransform());
5794}
5795
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005796TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00005797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Prabir Pradhanfb549072023-10-05 19:17:36 +00005798 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00005799
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005800 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08005802 << "Injection should fail if there is a monitor, but no touchable window";
5803 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00005804}
5805
Linnan Lid8150952024-01-26 18:07:17 +00005806/**
5807 * Two displays
5808 * The first monitor has a foreground window, a monitor
5809 * The second window has only one monitor.
5810 * We first inject a Down event into the first display, this injection should succeed and both
5811 * the foreground window and monitor should receive a down event, then inject a Down event into
5812 * the second display as well, this injection should fail, at this point, the first display
5813 * window and monitor should not receive a cancel or any other event.
5814 * Continue to inject Move and UP events to the first display, the events should be received
5815 * normally by the foreground window and monitor.
5816 */
5817TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
5818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5819 sp<FakeWindowHandle> window =
5820 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
5821
5822 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5823 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
5824
5825 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5827 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5828 {100, 200}))
5829 << "The down event injected into the first display should succeed";
5830
5831 window->consumeMotionDown();
5832 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00005833
5834 ASSERT_EQ(InputEventInjectionResult::FAILED,
5835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5836 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005837 << "The down event injected into the second display should fail since there's no "
5838 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00005839
5840 // Continue to inject event to first display.
5841 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5842 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5843 ADISPLAY_ID_DEFAULT, {110, 220}))
5844 << "The move event injected into the first display should succeed";
5845
5846 window->consumeMotionMove();
5847 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00005848
5849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5850 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5851 {110, 220}))
5852 << "The up event injected into the first display should succeed";
5853
5854 window->consumeMotionUp();
5855 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005856
5857 window->assertNoEvents();
5858 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00005859 secondMonitor.assertNoEvents();
5860}
5861
5862/**
5863 * Two displays
5864 * There is a monitor and foreground window on each display.
5865 * First, we inject down events into each of the two displays, at this point, the foreground windows
5866 * and monitors on both displays should receive down events.
5867 * At this point, the foreground window of the second display goes away, the gone window should
5868 * receive the cancel event, and the other windows and monitors should not receive any events.
5869 * Inject a move event into the second display. At this point, the injection should fail because
5870 * the second display no longer has a foreground window. At this point, the monitor on the second
5871 * display should receive a cancel event, and any windows or monitors on the first display should
5872 * not receive any events, and any subsequent injection of events into the second display should
5873 * also fail.
5874 * Continue to inject events into the first display, and the events should all be injected
5875 * successfully and received normally.
5876 */
5877TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
5878 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5879 sp<FakeWindowHandle> window =
5880 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
5881 sp<FakeWindowHandle> secondWindow =
5882 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
5883 SECOND_DISPLAY_ID);
5884
5885 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5886 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
5887
5888 // There is a foreground window on both displays.
5889 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
5890 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5891 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5892 {100, 200}))
5893 << "The down event injected into the first display should succeed";
5894
5895 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
5896 monitor.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00005897
5898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5899 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5900 {100, 200}))
5901 << "The down event injected into the second display should succeed";
5902
Linnan Lid8150952024-01-26 18:07:17 +00005903 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
5904 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
5905
5906 // Now second window is gone away.
5907 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5908
5909 // The gone window should receive a cancel, and the monitor on the second display should not
5910 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00005911 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
5912 secondMonitor.assertNoEvents();
5913
5914 ASSERT_EQ(InputEventInjectionResult::FAILED,
5915 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5916 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005917 << "The move event injected into the second display should fail because there's no "
5918 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00005919 // Now the monitor on the second display should receive a cancel event.
5920 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00005921
5922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5923 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5924 ADISPLAY_ID_DEFAULT, {110, 200}))
5925 << "The move event injected into the first display should succeed";
5926
5927 window->consumeMotionMove();
5928 monitor.consumeMotionMove(ADISPLAY_ID_DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00005929
5930 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005931 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
5932 {110, 220}))
5933 << "The up event injected into the second display should fail because there's no "
5934 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00005935
5936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5937 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5938 {110, 220}))
5939 << "The up event injected into the first display should succeed";
5940
5941 window->consumeMotionUp(ADISPLAY_ID_DEFAULT);
5942 monitor.consumeMotionUp(ADISPLAY_ID_DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005943
Linnan Lid8150952024-01-26 18:07:17 +00005944 window->assertNoEvents();
5945 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005946 secondWindow->assertNoEvents();
5947 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00005948}
5949
5950/**
5951 * One display with transform
5952 * There is a foreground window and a monitor on the display
5953 * Inject down event and move event sequentially, the foreground window and monitor can receive down
5954 * event and move event, then let the foreground window go away, the foreground window receives
5955 * cancel event, inject move event again, the monitor receives cancel event, all the events received
5956 * by the monitor should be with the same transform as the display
5957 */
5958TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
5959 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5960 sp<FakeWindowHandle> window =
5961 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground", ADISPLAY_ID_DEFAULT);
5962 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
5963
5964 ui::Transform transform;
5965 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
5966
5967 gui::DisplayInfo displayInfo;
5968 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
5969 displayInfo.transform = transform;
5970
5971 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
5972
5973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5974 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
5975 {100, 200}))
5976 << "The down event injected should succeed";
5977
5978 window->consumeMotionDown();
5979 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
5980 EXPECT_EQ(transform, downMotionEvent->getTransform());
5981 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
5982
5983 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5984 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
5985 ADISPLAY_ID_DEFAULT, {110, 220}))
5986 << "The move event injected should succeed";
5987
5988 window->consumeMotionMove();
5989 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
5990 EXPECT_EQ(transform, moveMotionEvent->getTransform());
5991 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
5992
5993 // Let foreground window gone
5994 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
5995
Prabir Pradhana0d43d42024-01-30 00:27:08 +00005996 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00005997 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00005998
5999 ASSERT_EQ(InputEventInjectionResult::FAILED,
6000 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
6001 ADISPLAY_ID_DEFAULT, {110, 220}))
6002 << "The move event injected should failed";
6003 // Now foreground should not receive any events, but monitor should receive a cancel event
6004 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00006005 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
6006 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
6007 EXPECT_EQ(ADISPLAY_ID_DEFAULT, cancelMotionEvent->getDisplayId());
6008 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
6009
6010 // Other event inject to this display should fail.
6011 ASSERT_EQ(InputEventInjectionResult::FAILED,
6012 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6013 ADISPLAY_ID_DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006014 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00006015 window->assertNoEvents();
6016 monitor.assertNoEvents();
6017}
6018
chaviw81e2bb92019-12-18 15:03:51 -08006019TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006021 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6022 "Fake Window", ADISPLAY_ID_DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08006023
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006024 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08006025
6026 NotifyMotionArgs motionArgs =
6027 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6028 ADISPLAY_ID_DEFAULT);
6029
Prabir Pradhan678438e2023-04-13 19:32:51 +00006030 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08006031 // Window should receive motion down event.
6032 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
6033
6034 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08006035 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08006036 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
6037 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6038 motionArgs.pointerCoords[0].getX() - 10);
6039
Prabir Pradhan678438e2023-04-13 19:32:51 +00006040 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00006041 window->consumeMotionMove(ADISPLAY_ID_DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08006042}
6043
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006044/**
6045 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
6046 * the device default right away. In the test scenario, we check both the default value,
6047 * and the action of enabling / disabling.
6048 */
6049TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07006050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006051 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6052 "Test window", ADISPLAY_ID_DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08006053 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006054
6055 // Set focused application.
6056 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006057 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006058
6059 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006060 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006061 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006062 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006063
6064 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006065 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006066 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006067 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006068
6069 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006070 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006071 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006072 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07006073 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006074 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006075 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006076 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006077
6078 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07006079 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006080 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00006081 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006082
6083 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08006084 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +00006085 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00006086 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07006087 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006088 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006089 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00006090 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006091
6092 window->assertNoEvents();
6093}
6094
Gang Wange9087892020-01-07 12:17:14 -05006095TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006096 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006097 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6098 "Test window", ADISPLAY_ID_DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05006099
6100 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07006101 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05006102
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006103 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006104 setFocusedWindow(window);
6105
Harry Cutts33476232023-01-30 19:57:29 +00006106 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05006107
Prabir Pradhan678438e2023-04-13 19:32:51 +00006108 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
6109 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05006110
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006111 std::unique_ptr<KeyEvent> event = window->consumeKey();
6112 ASSERT_NE(event, nullptr);
6113 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05006114 ASSERT_NE(verified, nullptr);
6115 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
6116
6117 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
6118 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
6119 ASSERT_EQ(keyArgs.source, verified->source);
6120 ASSERT_EQ(keyArgs.displayId, verified->displayId);
6121
6122 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
6123
6124 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05006125 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006126 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05006127 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
6128 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
6129 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
6130 ASSERT_EQ(0, verifiedKey.repeatCount);
6131}
6132
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006133TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006134 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006135 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
6136 "Test window", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006137
6138 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6139
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006140 ui::Transform transform;
6141 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
6142
6143 gui::DisplayInfo displayInfo;
6144 displayInfo.displayId = ADISPLAY_ID_DEFAULT;
6145 displayInfo.transform = transform;
6146
Patrick Williamsd828f302023-04-28 17:52:08 -05006147 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006148
Prabir Pradhan678438e2023-04-13 19:32:51 +00006149 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006150 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6151 ADISPLAY_ID_DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00006152 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006153
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006154 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
6155 ASSERT_NE(nullptr, event);
6156 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006157 ASSERT_NE(verified, nullptr);
6158 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
6159
6160 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
6161 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
6162 EXPECT_EQ(motionArgs.source, verified->source);
6163 EXPECT_EQ(motionArgs.displayId, verified->displayId);
6164
6165 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
6166
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07006167 const vec2 rawXY =
6168 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
6169 motionArgs.pointerCoords[0].getXYValue());
6170 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
6171 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006172 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006173 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08006174 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08006175 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
6176 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
6177}
6178
chaviw09c8d2d2020-08-24 15:48:26 -07006179/**
6180 * Ensure that separate calls to sign the same data are generating the same key.
6181 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
6182 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
6183 * tests.
6184 */
6185TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
6186 KeyEvent event = getTestKeyEvent();
6187 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6188
6189 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
6190 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
6191 ASSERT_EQ(hmac1, hmac2);
6192}
6193
6194/**
6195 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
6196 */
6197TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
6198 KeyEvent event = getTestKeyEvent();
6199 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
6200 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
6201
6202 verifiedEvent.deviceId += 1;
6203 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6204
6205 verifiedEvent.source += 1;
6206 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6207
6208 verifiedEvent.eventTimeNanos += 1;
6209 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6210
6211 verifiedEvent.displayId += 1;
6212 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6213
6214 verifiedEvent.action += 1;
6215 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6216
6217 verifiedEvent.downTimeNanos += 1;
6218 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6219
6220 verifiedEvent.flags += 1;
6221 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6222
6223 verifiedEvent.keyCode += 1;
6224 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6225
6226 verifiedEvent.scanCode += 1;
6227 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6228
6229 verifiedEvent.metaState += 1;
6230 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6231
6232 verifiedEvent.repeatCount += 1;
6233 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
6234}
6235
Vishnu Nair958da932020-08-21 17:12:37 -07006236TEST_F(InputDispatcherTest, SetFocusedWindow) {
6237 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6238 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006239 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006240 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006241 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006242 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6243
6244 // Top window is also focusable but is not granted focus.
6245 windowTop->setFocusable(true);
6246 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006247 mDispatcher->onWindowInfosChanged(
6248 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006249 setFocusedWindow(windowSecond);
6250
6251 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006253 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006254
6255 // Focused window should receive event.
6256 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6257 windowTop->assertNoEvents();
6258}
6259
6260TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
6261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6262 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006263 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006264 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6265
6266 window->setFocusable(true);
6267 // Release channel for window is no longer valid.
6268 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006269 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006270 setFocusedWindow(window);
6271
6272 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006273 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006274
6275 // window channel is invalid, so it should not receive any input event.
6276 window->assertNoEvents();
6277}
6278
6279TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
6280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6281 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006282 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006283 window->setFocusable(false);
Vishnu Nair958da932020-08-21 17:12:37 -07006284 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6285
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006286 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006287 setFocusedWindow(window);
6288
6289 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006290 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07006291
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006292 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07006293 window->assertNoEvents();
6294}
6295
6296TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
6297 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6298 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006299 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006300 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006301 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006302 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6303
6304 windowTop->setFocusable(true);
6305 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006306 mDispatcher->onWindowInfosChanged(
6307 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006308 setFocusedWindow(windowTop);
6309 windowTop->consumeFocusEvent(true);
6310
Chavi Weingarten847e8512023-03-29 00:26:09 +00006311 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006312 mDispatcher->onWindowInfosChanged(
6313 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006314 windowSecond->consumeFocusEvent(true);
6315 windowTop->consumeFocusEvent(false);
6316
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006318 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006319
6320 // Focused window should receive event.
6321 windowSecond->consumeKeyDown(ADISPLAY_ID_NONE);
6322}
6323
Chavi Weingarten847e8512023-03-29 00:26:09 +00006324TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07006325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6326 sp<FakeWindowHandle> windowTop =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006327 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006328 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006329 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006330 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6331
6332 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00006333 windowSecond->setFocusable(false);
6334 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006335 mDispatcher->onWindowInfosChanged(
6336 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00006337 setFocusedWindow(windowTop);
6338 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07006339
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00006341 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07006342
6343 // Event should be dropped.
Chavi Weingarten847e8512023-03-29 00:26:09 +00006344 windowTop->consumeKeyDown(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07006345 windowSecond->assertNoEvents();
6346}
6347
6348TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
6349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6350 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006351 sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006352 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006353 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
6354 ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07006355 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6356
6357 window->setFocusable(true);
6358 previousFocusedWindow->setFocusable(true);
6359 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006360 mDispatcher->onWindowInfosChanged(
6361 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006362 setFocusedWindow(previousFocusedWindow);
6363 previousFocusedWindow->consumeFocusEvent(true);
6364
6365 // Requesting focus on invisible window takes focus from currently focused window.
6366 setFocusedWindow(window);
6367 previousFocusedWindow->consumeFocusEvent(false);
6368
6369 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006371 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
6372 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07006373
6374 // Window does not get focus event or key down.
6375 window->assertNoEvents();
6376
6377 // Window becomes visible.
6378 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006380
6381 // Window receives focus event.
6382 window->consumeFocusEvent(true);
6383 // Focused window receives key down.
6384 window->consumeKeyDown(ADISPLAY_ID_DEFAULT);
6385}
6386
Vishnu Nair599f1412021-06-21 10:39:58 -07006387TEST_F(InputDispatcherTest, DisplayRemoved) {
6388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6389 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006390 sp<FakeWindowHandle>::make(application, mDispatcher, "window", ADISPLAY_ID_DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07006391 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6392
6393 // window is granted focus.
6394 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006395 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07006396 setFocusedWindow(window);
6397 window->consumeFocusEvent(true);
6398
6399 // When a display is removed window loses focus.
6400 mDispatcher->displayRemoved(ADISPLAY_ID_DEFAULT);
6401 window->consumeFocusEvent(false);
6402}
6403
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006404/**
6405 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
6406 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
6407 * of the 'slipperyEnterWindow'.
6408 *
6409 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
6410 * a way so that the touched location is no longer covered by the top window.
6411 *
6412 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
6413 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
6414 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
6415 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
6416 * with ACTION_DOWN).
6417 * Thus, the touch has been transferred from the top window into the bottom window, because the top
6418 * window moved itself away from the touched location and had Flag::SLIPPERY.
6419 *
6420 * Even though the top window moved away from the touched location, it is still obscuring the bottom
6421 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
6422 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
6423 *
6424 * In this test, we ensure that the event received by the bottom window has
6425 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
6426 */
6427TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006428 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006429 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006430
6431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6432 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
6433
6434 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006435 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08006436 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006437 // Make sure this one overlaps the bottom window
6438 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
6439 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
6440 // one. Windows with the same owner are not considered to be occluding each other.
6441 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
6442
6443 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006444 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006445 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
6446
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006447 mDispatcher->onWindowInfosChanged(
6448 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006449
6450 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00006451 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
6452 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6453 {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006454 slipperyExitWindow->consumeMotionDown();
6455 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006456 mDispatcher->onWindowInfosChanged(
6457 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006458
Prabir Pradhan678438e2023-04-13 19:32:51 +00006459 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
6460 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
6461 {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006462
6463 slipperyExitWindow->consumeMotionCancel();
6464
6465 slipperyEnterWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT,
6466 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6467}
6468
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006469/**
6470 * Two windows, one on the left and another on the right. The left window is slippery. The right
6471 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
6472 * touch moves from the left window into the right window, the gesture should continue to go to the
6473 * left window. Touch shouldn't slip because the right window can't receive touches. This test
6474 * reproduces a crash.
6475 */
6476TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
6477 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6478
6479 sp<FakeWindowHandle> leftSlipperyWindow =
6480 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6481 leftSlipperyWindow->setSlippery(true);
6482 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
6483
6484 sp<FakeWindowHandle> rightDropTouchesWindow =
6485 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6486 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
6487 rightDropTouchesWindow->setDropInput(true);
6488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006489 mDispatcher->onWindowInfosChanged(
6490 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07006491
6492 // Start touch in the left window
6493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6494 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6495 .build());
6496 leftSlipperyWindow->consumeMotionDown();
6497
6498 // And move it into the right window
6499 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6500 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6501 .build());
6502
6503 // Since the right window isn't eligible to receive input, touch does not slip.
6504 // The left window continues to receive the gesture.
6505 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6506 rightDropTouchesWindow->assertNoEvents();
6507}
6508
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07006509/**
6510 * A single window is on screen first. Touch is injected into that window. Next, a second window
6511 * appears. Since the first window is slippery, touch will move from the first window to the second.
6512 */
6513TEST_F(InputDispatcherTest, InjectedTouchSlips) {
6514 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6515 sp<FakeWindowHandle> originalWindow =
6516 sp<FakeWindowHandle>::make(application, mDispatcher, "Original", ADISPLAY_ID_DEFAULT);
6517 originalWindow->setFrame(Rect(0, 0, 200, 200));
6518 originalWindow->setSlippery(true);
6519
6520 sp<FakeWindowHandle> appearingWindow =
6521 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing", ADISPLAY_ID_DEFAULT);
6522 appearingWindow->setFrame(Rect(0, 0, 200, 200));
6523
6524 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
6525
6526 // Touch down on the original window
6527 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6528 injectMotionEvent(*mDispatcher,
6529 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6530 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
6531 .build()));
6532 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6533
6534 // Now, a new window appears. This could be, for example, a notification shade that appears
6535 // after user starts to drag down on the launcher window.
6536 mDispatcher->onWindowInfosChanged(
6537 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
6538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6539 injectMotionEvent(*mDispatcher,
6540 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6541 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
6542 .build()));
6543 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
6544 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
6546 injectMotionEvent(*mDispatcher,
6547 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6548 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6549 .build()));
6550 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6551
6552 originalWindow->assertNoEvents();
6553 appearingWindow->assertNoEvents();
6554}
6555
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006556TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006557 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006558 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6559
6560 sp<FakeWindowHandle> leftWindow =
6561 sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT);
6562 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006563 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006564
6565 sp<FakeWindowHandle> rightSpy =
6566 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy", ADISPLAY_ID_DEFAULT);
6567 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006568 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006569 rightSpy->setSpy(true);
6570 rightSpy->setTrustedOverlay(true);
6571
6572 sp<FakeWindowHandle> rightWindow =
6573 sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT);
6574 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006575 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006576
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006577 mDispatcher->onWindowInfosChanged(
6578 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006579
6580 // Touch in the left window
6581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6582 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6583 .build());
6584 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
6585 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006586 ASSERT_NO_FATAL_FAILURE(
6587 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006588
6589 // Touch another finger over the right windows
6590 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6591 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6592 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6593 .build());
6594 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
6595 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
6596 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
6597 mDispatcher->waitForIdle();
6598 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006599 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
6600 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006601
6602 // Release finger over left window. The UP actions are not treated as device interaction.
6603 // The windows that did not receive the UP pointer will receive MOVE events, but since this
6604 // is part of the UP action, we do not treat this as device interaction.
6605 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
6606 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6607 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6608 .build());
6609 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
6610 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6611 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6612 mDispatcher->waitForIdle();
6613 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6614
6615 // Move remaining finger
6616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
6617 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6618 .build());
6619 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
6620 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
6621 mDispatcher->waitForIdle();
6622 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006623 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006624
6625 // Release all fingers
6626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6627 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
6628 .build());
6629 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
6630 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
6631 mDispatcher->waitForIdle();
6632 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6633}
6634
6635TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
6636 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6637
6638 sp<FakeWindowHandle> window =
6639 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6640 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00006641 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006642
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006643 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006644 setFocusedWindow(window);
6645 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
6646
6647 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
6648 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ADISPLAY_ID_DEFAULT));
6649 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00006650 ASSERT_NO_FATAL_FAILURE(
6651 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00006652
6653 // The UP actions are not treated as device interaction.
6654 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
6655 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ADISPLAY_ID_DEFAULT));
6656 mDispatcher->waitForIdle();
6657 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
6658}
6659
Prabir Pradhan5893d362023-11-17 04:30:40 +00006660TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
6661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6662
6663 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
6664 ADISPLAY_ID_DEFAULT);
6665 left->setFrame(Rect(0, 0, 100, 100));
6666 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
6667 "Right Window", ADISPLAY_ID_DEFAULT);
6668 right->setFrame(Rect(100, 0, 200, 100));
6669 sp<FakeWindowHandle> spy =
6670 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
6671 spy->setFrame(Rect(0, 0, 200, 100));
6672 spy->setTrustedOverlay(true);
6673 spy->setSpy(true);
6674
6675 mDispatcher->onWindowInfosChanged(
6676 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
6677
6678 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
6679 NotifyMotionArgs notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
6680 ADISPLAY_ID_DEFAULT, {PointF{50, 50}});
6681 mDispatcher->notifyMotion(notifyArgs);
6682
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006683 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00006684 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
6685 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006686 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00006687 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6688 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006689 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00006690 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6691
6692 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
6693 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
6694 {PointF{150, 50}});
6695 mDispatcher->notifyMotion(notifyArgs);
6696
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006697 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00006698 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
6699 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006700 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00006701 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6702 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006703 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00006704 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
6705
6706 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
6707}
6708
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006709class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
6710protected:
6711 std::shared_ptr<FakeApplicationHandle> mApp;
6712 sp<FakeWindowHandle> mWindow;
6713
6714 virtual void SetUp() override {
6715 InputDispatcherTest::SetUp();
6716
6717 mApp = std::make_shared<FakeApplicationHandle>();
6718
6719 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
6720 mWindow->setFrame(Rect(0, 0, 100, 100));
6721
6722 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
6723 setFocusedWindow(mWindow);
6724 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
6725 }
6726
6727 void setFallback(int32_t keycode) {
6728 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
6729 return KeyEventBuilder(event).keyCode(keycode).build();
6730 });
6731 }
6732
6733 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006734 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
6735 ASSERT_NE(nullptr, event);
6736 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00006737 }
6738};
6739
6740TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
6741 mDispatcher->notifyKey(
6742 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6743 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6744 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6745}
6746
6747TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
6748 mDispatcher->notifyKey(
6749 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6750 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
6751 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6752}
6753
6754TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
6755 mDispatcher->notifyKey(
6756 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6757
6758 // Do not handle this key event.
6759 consumeKey(/*handled=*/false,
6760 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6761 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6762
6763 // Since the policy did not request any fallback to be generated, ensure there are no events.
6764 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6765}
6766
6767TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
6768 setFallback(AKEYCODE_B);
6769 mDispatcher->notifyKey(
6770 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6771
6772 // Do not handle this key event.
6773 consumeKey(/*handled=*/false,
6774 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6775
6776 // Since the key was not handled, ensure the fallback event was dispatched instead.
6777 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6778 consumeKey(/*handled=*/true,
6779 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6780 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6781
6782 // Release the original key, and ensure the fallback key is also released.
6783 mDispatcher->notifyKey(
6784 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6785 consumeKey(/*handled=*/false,
6786 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6787 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6788 consumeKey(/*handled=*/true,
6789 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6790 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6791
6792 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6793 mWindow->assertNoEvents();
6794}
6795
6796TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
6797 setFallback(AKEYCODE_B);
6798 mDispatcher->notifyKey(
6799 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6800
6801 // Do not handle this key event, but handle the fallback.
6802 consumeKey(/*handled=*/false,
6803 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6804 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6805 consumeKey(/*handled=*/true,
6806 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6807 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6808
6809 // Release the original key, and ensure the fallback key is also released.
6810 mDispatcher->notifyKey(
6811 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6812 // But this time, the app handles the original key.
6813 consumeKey(/*handled=*/true,
6814 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6815 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6816 // Ensure the fallback key is canceled.
6817 consumeKey(/*handled=*/true,
6818 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6819 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6820
6821 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6822 mWindow->assertNoEvents();
6823}
6824
6825TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
6826 setFallback(AKEYCODE_B);
6827 mDispatcher->notifyKey(
6828 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6829
6830 // Do not handle this key event.
6831 consumeKey(/*handled=*/false,
6832 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6833 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6834 // App does not handle the fallback either, so ensure another fallback is not generated.
6835 setFallback(AKEYCODE_C);
6836 consumeKey(/*handled=*/false,
6837 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6838 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6839
6840 // Release the original key, and ensure the fallback key is also released.
6841 setFallback(AKEYCODE_B);
6842 mDispatcher->notifyKey(
6843 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6844 consumeKey(/*handled=*/false,
6845 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6846 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6847 consumeKey(/*handled=*/false,
6848 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6849 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6850
6851 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6852 mWindow->assertNoEvents();
6853}
6854
6855TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
6856 setFallback(AKEYCODE_B);
6857 mDispatcher->notifyKey(
6858 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6859
6860 // Do not handle this key event, so fallback is generated.
6861 consumeKey(/*handled=*/false,
6862 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6863 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6864 consumeKey(/*handled=*/true,
6865 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6866 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6867
6868 // Release the original key, but assume the policy is misbehaving and it
6869 // generates an inconsistent fallback to the one from the DOWN event.
6870 setFallback(AKEYCODE_C);
6871 mDispatcher->notifyKey(
6872 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6873 consumeKey(/*handled=*/false,
6874 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6875 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6876 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
6877 consumeKey(/*handled=*/true,
6878 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6879 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6880
6881 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6882 mWindow->assertNoEvents();
6883}
6884
6885TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
6886 setFallback(AKEYCODE_B);
6887 mDispatcher->notifyKey(
6888 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6889
6890 // Do not handle this key event, so fallback is generated.
6891 consumeKey(/*handled=*/false,
6892 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6893 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6894 consumeKey(/*handled=*/true,
6895 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6896 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6897
6898 // The original key is canceled.
6899 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
6900 .keyCode(AKEYCODE_A)
6901 .addFlag(AKEY_EVENT_FLAG_CANCELED)
6902 .build());
6903 consumeKey(/*handled=*/false,
6904 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
6905 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
6906 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6907 // Ensure the fallback key is also canceled due to the original key being canceled.
6908 consumeKey(/*handled=*/true,
6909 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6910 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6911
6912 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
6913 mWindow->assertNoEvents();
6914}
6915
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00006916TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00006917 setFallback(AKEYCODE_B);
6918 mDispatcher->notifyKey(
6919 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6920
6921 // Do not handle this key event.
6922 consumeKey(/*handled=*/false,
6923 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6924 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6925 consumeKey(/*handled=*/true,
6926 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6927 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6928
6929 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
6930 // When the unhandled key is reported to the policy next, remove the input channel.
6931 mDispatcher->removeInputChannel(mWindow->getToken());
6932 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
6933 });
6934 // Release the original key, and let the app now handle the previously unhandled key.
6935 // This should result in the previously generated fallback key to be cancelled.
6936 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
6937 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
6938 // without holding the lock, because it need to synchronously fetch the fallback key. While in
6939 // the policy call, we will now remove the input channel. Once the policy call returns, the
6940 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
6941 // not cause any crashes.
6942 mDispatcher->notifyKey(
6943 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6944 consumeKey(/*handled=*/true,
6945 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6946 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6947}
6948
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00006949TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
6950 setFallback(AKEYCODE_B);
6951 mDispatcher->notifyKey(
6952 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6953
6954 // Do not handle this key event.
6955 consumeKey(/*handled=*/false,
6956 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6957 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6958 consumeKey(/*handled=*/true,
6959 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6960 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6961
6962 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
6963 // When the unhandled key is reported to the policy next, remove the window.
6964 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
6965 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
6966 });
6967 // Release the original key, which the app will not handle. When this unhandled key is reported
6968 // to the policy, the window will be removed.
6969 mDispatcher->notifyKey(
6970 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6971 consumeKey(/*handled=*/false,
6972 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6973 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6974
6975 // Since the window was removed, it loses focus, and the channel state will be reset.
6976 consumeKey(/*handled=*/true,
6977 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
6978 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
6979 mWindow->consumeFocusEvent(false);
6980 mWindow->assertNoEvents();
6981}
6982
6983TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
6984 setFallback(AKEYCODE_B);
6985 mDispatcher->notifyKey(
6986 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
6987
6988 // Do not handle this key event.
6989 consumeKey(/*handled=*/false,
6990 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
6991 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
6992 const auto [seq, event] = mWindow->receiveEvent();
6993 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
6994 ASSERT_EQ(event->getType(), InputEventType::KEY);
6995 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
6996 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
6997 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
6998
6999 // Remove the window now, which should generate a cancellations and make the window lose focus.
7000 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
7001 consumeKey(/*handled=*/true,
7002 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
7003 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7004 consumeKey(/*handled=*/true,
7005 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
7006 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
7007 mWindow->consumeFocusEvent(false);
7008
7009 // Finish the event by reporting it as handled.
7010 mWindow->finishEvent(*seq);
7011 mWindow->assertNoEvents();
7012}
7013
Garfield Tan1c7bc862020-01-28 13:24:04 -08007014class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
7015protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08007016 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
7017 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007018
Chris Yea209fde2020-07-22 13:54:51 -07007019 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007020 sp<FakeWindowHandle> mWindow;
7021
7022 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00007023 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007024
Prabir Pradhandae52792023-12-15 07:36:40 +00007025 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007026 setUpWindow();
7027 }
7028
7029 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07007030 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007031 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007032
Vishnu Nair47074b82020-08-14 11:54:47 -07007033 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007034 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007035 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007036 mWindow->consumeFocusEvent(true);
7037 }
7038
Chris Ye2ad95392020-09-01 13:44:44 -07007039 void sendAndConsumeKeyDown(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007040 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007041 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007042 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007043 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007044
7045 // Window should receive key down event.
7046 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7047 }
7048
7049 void expectKeyRepeatOnce(int32_t repeatCount) {
7050 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007051 mWindow->consumeKeyEvent(
7052 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007053 }
7054
Chris Ye2ad95392020-09-01 13:44:44 -07007055 void sendAndConsumeKeyUp(int32_t deviceId) {
Garfield Tan1c7bc862020-01-28 13:24:04 -08007056 NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07007057 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08007058 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00007059 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007060
7061 // Window should receive key down event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007062 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00007063 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007064 }
Hu Guofe3c8f12023-09-22 17:20:15 +08007065
7066 void injectKeyRepeat(int32_t repeatCount) {
7067 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7068 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount, ADISPLAY_ID_DEFAULT))
7069 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
7070 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08007071};
7072
7073TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00007074 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007075 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7076 expectKeyRepeatOnce(repeatCount);
7077 }
7078}
7079
7080TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00007081 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007082 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7083 expectKeyRepeatOnce(repeatCount);
7084 }
Harry Cutts33476232023-01-30 19:57:29 +00007085 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007086 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08007087 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
7088 expectKeyRepeatOnce(repeatCount);
7089 }
7090}
7091
7092TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007093 sendAndConsumeKeyDown(/*deviceId=*/1);
7094 expectKeyRepeatOnce(/*repeatCount=*/1);
7095 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007096 mWindow->assertNoEvents();
7097}
7098
7099TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007100 sendAndConsumeKeyDown(/*deviceId=*/1);
7101 expectKeyRepeatOnce(/*repeatCount=*/1);
7102 sendAndConsumeKeyDown(/*deviceId=*/2);
7103 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007104 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00007105 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007106 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00007107 expectKeyRepeatOnce(/*repeatCount=*/2);
7108 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07007109 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00007110 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007111 mWindow->assertNoEvents();
7112}
7113
7114TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00007115 sendAndConsumeKeyDown(/*deviceId=*/1);
7116 expectKeyRepeatOnce(/*repeatCount=*/1);
7117 sendAndConsumeKeyDown(/*deviceId=*/2);
7118 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07007119 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00007120 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07007121 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08007122 mWindow->assertNoEvents();
7123}
7124
liushenxiang42232912021-05-21 20:24:09 +08007125TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
7126 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00007127 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007128 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
liushenxiang42232912021-05-21 20:24:09 +08007129 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
7130 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
7131 mWindow->assertNoEvents();
7132}
7133
Garfield Tan1c7bc862020-01-28 13:24:04 -08007134TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007135 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007136 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007137 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007138 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7139 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007140 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007141 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08007142 }
7143}
7144
7145TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00007146 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00007147 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08007148
7149 std::unordered_set<int32_t> idSet;
7150 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007151 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
7152 ASSERT_NE(nullptr, repeatEvent);
7153 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08007154 EXPECT_EQ(idSet.end(), idSet.find(id));
7155 idSet.insert(id);
7156 }
7157}
7158
Hu Guofe3c8f12023-09-22 17:20:15 +08007159TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
7160 injectKeyRepeat(0);
7161 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7162 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
7163 expectKeyRepeatOnce(repeatCount);
7164 }
7165 injectKeyRepeat(1);
7166 // Expect repeatCount to be 3 instead of 1
7167 expectKeyRepeatOnce(3);
7168}
7169
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007170/* Test InputDispatcher for MultiDisplay */
7171class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
7172public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007173 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007174 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08007175
Chris Yea209fde2020-07-22 13:54:51 -07007176 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007177 windowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007178 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007179
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007180 // Set focus window for primary display, but focused display would be second one.
7181 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07007182 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007183 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
7184
Vishnu Nair958da932020-08-21 17:12:37 -07007185 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007186 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08007187
Chris Yea209fde2020-07-22 13:54:51 -07007188 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007189 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007190 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007191 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007192 // Set focus display to second one.
7193 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
7194 // Set focus window for second display.
7195 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07007196 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007197 mDispatcher->onWindowInfosChanged(
7198 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007199 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007200 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007201 }
7202
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007203 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007204 InputDispatcherTest::TearDown();
7205
Chris Yea209fde2020-07-22 13:54:51 -07007206 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007207 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07007208 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007209 windowInSecondary.clear();
7210 }
7211
7212protected:
Chris Yea209fde2020-07-22 13:54:51 -07007213 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007214 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07007215 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007216 sp<FakeWindowHandle> windowInSecondary;
7217};
7218
7219TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
7220 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007222 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007223 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007224 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08007225 windowInSecondary->assertNoEvents();
7226
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007227 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007229 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007230 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007231 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007232 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08007233}
7234
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007235TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08007236 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007237 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007238 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007239 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007240 windowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08007241 windowInSecondary->assertNoEvents();
7242
7243 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007244 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007245 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08007246 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007247 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hungb92218b2018-08-14 12:00:21 +08007248
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007249 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007250 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08007251
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007252 // Old focus should receive a cancel event.
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007253 windowInSecondary->consumeKeyUp(ADISPLAY_ID_NONE, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08007254
7255 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007256 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08007257 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007258 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08007259 windowInSecondary->assertNoEvents();
7260}
7261
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007262// Test per-display input monitors for motion event.
7263TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08007264 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007265 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007266 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007267 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007268
7269 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007270 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007271 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007272 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007273 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007274 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007275 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007276 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007277
7278 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007280 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007281 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007282 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007283 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007284 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08007285 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007286
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007287 // Lift up the touch from the second display
7288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007289 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08007290 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7291 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
7292 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
7293
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007294 // Test inject a non-pointer motion event.
7295 // If specific a display, it will dispatch to the focused window of particular display,
7296 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007298 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_NONE))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007300 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007301 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007302 windowInSecondary->consumeMotionDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007303 monitorInSecondary.consumeMotionDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007304}
7305
7306// Test per-display input monitors for key event.
7307TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007308 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08007309 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007310 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08007311 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007312 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007313
7314 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007316 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007317 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08007318 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08007319 windowInSecondary->consumeKeyDown(ADISPLAY_ID_NONE);
chaviwd1c23182019-12-20 18:44:56 -08007320 monitorInSecondary.consumeKeyDown(ADISPLAY_ID_NONE);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08007321}
7322
Vishnu Nair958da932020-08-21 17:12:37 -07007323TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
7324 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007325 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2", ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007326 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007327 mDispatcher->onWindowInfosChanged(
7328 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
7329 *windowInSecondary->getInfo()},
7330 {},
7331 0,
7332 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007333 setFocusedWindow(secondWindowInPrimary);
7334 windowInPrimary->consumeFocusEvent(false);
7335 secondWindowInPrimary->consumeFocusEvent(true);
7336
7337 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7339 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007340 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007341 windowInPrimary->assertNoEvents();
7342 windowInSecondary->assertNoEvents();
7343 secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
7344}
7345
Arthur Hungdfd528e2021-12-08 13:23:04 +00007346TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
7347 FakeMonitorReceiver monitorInPrimary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007348 FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007349 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00007350 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00007351
7352 // Test touch down on primary display.
7353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007354 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007355 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7356 windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
7357 monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
7358
7359 // Test touch down on second display.
7360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00007362 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7363 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
7364 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
7365
7366 // Trigger cancel touch.
7367 mDispatcher->cancelCurrentTouch();
7368 windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7369 monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
7370 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
7371 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
7372
7373 // Test inject a move motion event, no window/monitor should receive the event.
7374 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007375 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007376 ADISPLAY_ID_DEFAULT, {110, 200}))
7377 << "Inject motion event should return InputEventInjectionResult::FAILED";
7378 windowInPrimary->assertNoEvents();
7379 monitorInPrimary.assertNoEvents();
7380
7381 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007382 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00007383 SECOND_DISPLAY_ID, {110, 200}))
7384 << "Inject motion event should return InputEventInjectionResult::FAILED";
7385 windowInSecondary->assertNoEvents();
7386 monitorInSecondary.assertNoEvents();
7387}
7388
Hu Guocb134f12023-12-23 13:42:44 +00007389/**
7390 * Send a key to the primary display and to the secondary display.
7391 * Then cause the key on the primary display to be canceled by sending in a stale key.
7392 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
7393 * does not get canceled.
7394 */
7395TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
7396 // Send a key down on primary display
7397 mDispatcher->notifyKey(
7398 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7399 .displayId(ADISPLAY_ID_DEFAULT)
7400 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7401 .build());
7402 windowInPrimary->consumeKeyEvent(
7403 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7404 windowInSecondary->assertNoEvents();
7405
7406 // Send a key down on second display
7407 mDispatcher->notifyKey(
7408 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7409 .displayId(SECOND_DISPLAY_ID)
7410 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7411 .build());
7412 windowInSecondary->consumeKeyEvent(
7413 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7414 windowInPrimary->assertNoEvents();
7415
7416 // Send a valid key up event on primary display that will be dropped because it is stale
7417 NotifyKeyArgs staleKeyUp =
7418 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
7419 .displayId(ADISPLAY_ID_DEFAULT)
7420 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
7421 .build();
7422 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7423 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7424 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7425 mDispatcher->notifyKey(staleKeyUp);
7426
7427 // Only the key gesture corresponding to the dropped event should receive the cancel event.
7428 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
7429 // receive any events.
7430 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
7431 WithDisplayId(ADISPLAY_ID_DEFAULT),
7432 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
7433 windowInSecondary->assertNoEvents();
7434}
7435
7436/**
7437 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
7438 */
7439TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
7440 // Send touch down on primary display.
7441 mDispatcher->notifyMotion(
7442 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7443 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7444 .displayId(ADISPLAY_ID_DEFAULT)
7445 .build());
7446 windowInPrimary->consumeMotionEvent(
7447 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ADISPLAY_ID_DEFAULT)));
7448 windowInSecondary->assertNoEvents();
7449
7450 // Send touch down on second display.
7451 mDispatcher->notifyMotion(
7452 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7453 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7454 .displayId(SECOND_DISPLAY_ID)
7455 .build());
7456 windowInPrimary->assertNoEvents();
7457 windowInSecondary->consumeMotionEvent(
7458 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
7459
7460 // inject a valid MotionEvent on primary display that will be stale when it arrives.
7461 NotifyMotionArgs staleMotionUp =
7462 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7463 .displayId(ADISPLAY_ID_DEFAULT)
7464 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
7465 .build();
7466 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
7467 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
7468 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
7469 mDispatcher->notifyMotion(staleMotionUp);
7470
7471 // For stale motion events, we let the gesture to complete. This behaviour is different from key
7472 // events, where we would cancel the current keys instead.
7473 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
7474 windowInSecondary->assertNoEvents();
7475}
7476
Jackal Guof9696682018-10-05 12:23:23 +08007477class InputFilterTest : public InputDispatcherTest {
7478protected:
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007479 void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
7480 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08007481 NotifyMotionArgs motionArgs;
7482
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007483 motionArgs =
7484 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007485 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007486 motionArgs =
7487 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007488 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007489 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007490 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07007491 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007492 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08007493 } else {
7494 mFakePolicy->assertFilterInputEventWasNotCalled();
7495 }
7496 }
7497
7498 void testNotifyKey(bool expectToBeFiltered) {
7499 NotifyKeyArgs keyArgs;
7500
7501 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007502 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007503 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007504 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007505 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08007506
7507 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08007508 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08007509 } else {
7510 mFakePolicy->assertFilterInputEventWasNotCalled();
7511 }
7512 }
7513};
7514
7515// Test InputFilter for MotionEvent
7516TEST_F(InputFilterTest, MotionEvent_InputFilter) {
7517 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007518 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7519 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007520
7521 // Enable InputFilter
7522 mDispatcher->setInputFilterEnabled(true);
7523 // Test touch on both primary and second display, and check if both events are filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007524 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true);
7525 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007526
7527 // Disable InputFilter
7528 mDispatcher->setInputFilterEnabled(false);
7529 // Test touch on both primary and second display, and check if both events aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007530 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/false);
7531 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007532}
7533
7534// Test InputFilter for KeyEvent
7535TEST_F(InputFilterTest, KeyEvent_InputFilter) {
7536 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007537 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007538
7539 // Enable InputFilter
7540 mDispatcher->setInputFilterEnabled(true);
7541 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007542 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08007543
7544 // Disable InputFilter
7545 mDispatcher->setInputFilterEnabled(false);
7546 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007547 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08007548}
7549
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007550// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
7551// logical display coordinate space.
7552TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
7553 ui::Transform firstDisplayTransform;
7554 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7555 ui::Transform secondDisplayTransform;
7556 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
7557
7558 std::vector<gui::DisplayInfo> displayInfos(2);
7559 displayInfos[0].displayId = ADISPLAY_ID_DEFAULT;
7560 displayInfos[0].transform = firstDisplayTransform;
7561 displayInfos[1].displayId = SECOND_DISPLAY_ID;
7562 displayInfos[1].transform = secondDisplayTransform;
7563
Patrick Williamsd828f302023-04-28 17:52:08 -05007564 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007565
7566 // Enable InputFilter
7567 mDispatcher->setInputFilterEnabled(true);
7568
7569 // Ensure the correct transforms are used for the displays.
Harry Cutts101ee9b2023-07-06 18:04:14 +00007570 testNotifyMotion(ADISPLAY_ID_DEFAULT, /*expectToBeFiltered=*/true, firstDisplayTransform);
7571 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07007572}
7573
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007574class InputFilterInjectionPolicyTest : public InputDispatcherTest {
7575protected:
7576 virtual void SetUp() override {
7577 InputDispatcherTest::SetUp();
7578
7579 /**
7580 * We don't need to enable input filter to test the injected event policy, but we enabled it
7581 * here to make the tests more realistic, since this policy only matters when inputfilter is
7582 * on.
7583 */
7584 mDispatcher->setInputFilterEnabled(true);
7585
7586 std::shared_ptr<InputApplicationHandle> application =
7587 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007588 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
7589 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007590
7591 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7592 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007593 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007594 setFocusedWindow(mWindow);
7595 mWindow->consumeFocusEvent(true);
7596 }
7597
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007598 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7599 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007600 KeyEvent event;
7601
7602 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7603 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
7604 ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
Harry Cutts33476232023-01-30 19:57:29 +00007605 KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007606 const int32_t additionalPolicyFlags =
7607 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
7608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007609 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007610 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007611 policyFlags | additionalPolicyFlags));
7612
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007613 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007614 }
7615
7616 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
7617 int32_t flags) {
7618 MotionEvent event;
7619 PointerProperties pointerProperties[1];
7620 PointerCoords pointerCoords[1];
7621 pointerProperties[0].clear();
7622 pointerProperties[0].id = 0;
7623 pointerCoords[0].clear();
7624 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
7625 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
7626
7627 ui::Transform identityTransform;
7628 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7629 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
7630 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
7631 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
7632 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07007633 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07007634 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00007635 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007636
7637 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
7638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00007639 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00007640 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007641 policyFlags | additionalPolicyFlags));
7642
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007643 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007644 }
7645
7646private:
7647 sp<FakeWindowHandle> mWindow;
7648};
7649
7650TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007651 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
7652 // filter. Without it, the event will no different from a regularly injected event, and the
7653 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00007654 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
7655 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007656}
7657
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007658TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007659 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007660 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007661 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
7662}
7663
7664TEST_F(InputFilterInjectionPolicyTest,
7665 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
7666 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00007667 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00007668 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007669}
7670
7671TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00007672 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
7673 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00007674}
7675
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08007676class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
7677protected:
7678 virtual void SetUp() override {
7679 InputDispatcherTest::SetUp();
7680
7681 std::shared_ptr<FakeApplicationHandle> application =
7682 std::make_shared<FakeApplicationHandle>();
7683 application->setDispatchingTimeout(100ms);
7684 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7685 ADISPLAY_ID_DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00007686 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08007687 mWindow->setDispatchingTimeout(100ms);
7688 mWindow->setFocusable(true);
7689
7690 // Set focused application.
7691 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
7692
7693 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
7694 setFocusedWindow(mWindow);
7695 mWindow->consumeFocusEvent(true);
7696 }
7697
7698 void notifyAndConsumeMotion(int32_t action, uint32_t source, int32_t displayId,
7699 nsecs_t eventTime) {
7700 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
7701 .displayId(displayId)
7702 .eventTime(eventTime)
7703 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7704 .build());
7705 mWindow->consumeMotionEvent(WithMotionAction(action));
7706 }
7707
7708private:
7709 sp<FakeWindowHandle> mWindow;
7710};
7711
7712TEST_F_WITH_FLAGS(
7713 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
7714 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
7715 rate_limit_user_activity_poke_in_dispatcher))) {
7716 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
7717
7718 // First event of type TOUCH. Should poke.
7719 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7720 milliseconds_to_nanoseconds(50));
7721 mFakePolicy->assertUserActivityPoked(
7722 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7723
7724 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
7725 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7726 milliseconds_to_nanoseconds(130));
7727 mFakePolicy->assertUserActivityPoked(
7728 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7729
7730 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
7731 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
7732 milliseconds_to_nanoseconds(135));
7733 mFakePolicy->assertUserActivityPoked(
7734 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
7735
7736 // Within 50ns of previous TOUCH event. Should NOT poke.
7737 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7738 milliseconds_to_nanoseconds(140));
7739 mFakePolicy->assertUserActivityNotPoked();
7740
7741 // Within 50ns of previous OTHER event. Should NOT poke.
7742 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
7743 milliseconds_to_nanoseconds(150));
7744 mFakePolicy->assertUserActivityNotPoked();
7745
7746 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
7747 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
7748 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7749 milliseconds_to_nanoseconds(160));
7750 mFakePolicy->assertUserActivityNotPoked();
7751
7752 // 65ns > 50ns has passed since previous OTHER event. Should poke.
7753 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER, ADISPLAY_ID_DEFAULT,
7754 milliseconds_to_nanoseconds(200));
7755 mFakePolicy->assertUserActivityPoked(
7756 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER, ADISPLAY_ID_DEFAULT}});
7757
7758 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
7759 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ADISPLAY_ID_DEFAULT,
7760 milliseconds_to_nanoseconds(300));
7761 mFakePolicy->assertUserActivityPoked(
7762 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7763
7764 // Assert that there's no more user activity poke event.
7765 mFakePolicy->assertUserActivityNotPoked();
7766}
7767
7768TEST_F_WITH_FLAGS(
7769 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
7770 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
7771 rate_limit_user_activity_poke_in_dispatcher))) {
7772 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7773 milliseconds_to_nanoseconds(200));
7774 mFakePolicy->assertUserActivityPoked(
7775 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7776
7777 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7778 milliseconds_to_nanoseconds(280));
7779 mFakePolicy->assertUserActivityNotPoked();
7780
7781 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
7782 milliseconds_to_nanoseconds(340));
7783 mFakePolicy->assertUserActivityPoked(
7784 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH, ADISPLAY_ID_DEFAULT}});
7785}
7786
7787TEST_F_WITH_FLAGS(
7788 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
7789 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
7790 rate_limit_user_activity_poke_in_dispatcher))) {
7791 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
7792
7793 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20);
7794 mFakePolicy->assertUserActivityPoked();
7795
7796 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 30);
7797 mFakePolicy->assertUserActivityPoked();
7798}
7799
chaviwfd6d3512019-03-25 13:23:49 -07007800class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007801 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07007802 InputDispatcherTest::SetUp();
7803
Chris Yea209fde2020-07-22 13:54:51 -07007804 std::shared_ptr<FakeApplicationHandle> application =
7805 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007806 mUnfocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007807 sp<FakeWindowHandle>::make(application, mDispatcher, "Top", ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007808 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07007809
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007810 mFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007811 sp<FakeWindowHandle>::make(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007812 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07007813
7814 // Set focused application.
7815 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007816 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07007817
7818 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007819 mDispatcher->onWindowInfosChanged(
7820 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007821 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007822 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07007823 }
7824
Prabir Pradhan3608aad2019-10-02 17:08:26 -07007825 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07007826 InputDispatcherTest::TearDown();
7827
7828 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007829 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07007830 }
7831
7832protected:
7833 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08007834 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007835 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07007836};
7837
7838// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7839// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
7840// the onPointerDownOutsideFocus callback.
7841TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007842 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007843 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007844 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007846 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007847
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007848 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07007849 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
7850}
7851
7852// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
7853// DOWN on the window that doesn't have focus. Ensure no window received the
7854// onPointerDownOutsideFocus callback.
7855TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007857 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT,
7858 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007860 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007861
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007862 ASSERT_TRUE(mDispatcher->waitForIdle());
7863 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007864}
7865
7866// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
7867// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
7868TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08007869 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007870 injectKeyDownNoRepeat(*mDispatcher, ADISPLAY_ID_DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007871 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007872 mFocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07007873
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007874 ASSERT_TRUE(mDispatcher->waitForIdle());
7875 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007876}
7877
7878// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
7879// DOWN on the window that already has focus. Ensure no window received the
7880// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007881TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007882 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007883 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07007884 FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007885 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07007886 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07007887
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08007888 ASSERT_TRUE(mDispatcher->waitForIdle());
7889 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07007890}
7891
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007892// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
7893// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
7894TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
7895 const MotionEvent event =
7896 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
7897 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07007898 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007899 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
7900 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08007902 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7903 mUnfocusedWindow->consumeAnyMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
7904
7905 ASSERT_TRUE(mDispatcher->waitForIdle());
7906 mFakePolicy->assertOnPointerDownWasNotCalled();
7907 // Ensure that the unfocused window did not receive any FOCUS events.
7908 mUnfocusedWindow->assertNoEvents();
7909}
7910
chaviwaf87b3e2019-10-01 16:59:28 -07007911// These tests ensures we can send touch events to a single client when there are multiple input
7912// windows that point to the same client token.
7913class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
7914 virtual void SetUp() override {
7915 InputDispatcherTest::SetUp();
7916
Chris Yea209fde2020-07-22 13:54:51 -07007917 std::shared_ptr<FakeApplicationHandle> application =
7918 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007919 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
7920 ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007921 mWindow1->setFrame(Rect(0, 0, 100, 100));
7922
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00007923 mWindow2 = mWindow1->clone(ADISPLAY_ID_DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07007924 mWindow2->setFrame(Rect(100, 100, 200, 200));
7925
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007926 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007927 }
7928
7929protected:
7930 sp<FakeWindowHandle> mWindow1;
7931 sp<FakeWindowHandle> mWindow2;
7932
7933 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05007934 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07007935 vec2 vals = windowInfo->transform.transform(point.x, point.y);
7936 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07007937 }
7938
7939 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
7940 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007941 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007942 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00007943 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007944 ASSERT_NE(nullptr, motionEvent);
7945 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07007946
7947 for (size_t i = 0; i < points.size(); i++) {
7948 float expectedX = points[i].x;
7949 float expectedY = points[i].y;
7950
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007951 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007952 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007953 << ", got " << motionEvent->getX(i);
7954 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07007955 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007956 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07007957 }
7958 }
chaviw9eaa22c2020-07-01 16:21:27 -07007959
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007960 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
7961 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07007962 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00007963 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
7964 ADISPLAY_ID_DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07007965
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007966 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07007967 }
chaviwaf87b3e2019-10-01 16:59:28 -07007968};
7969
7970TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
7971 // Touch Window 1
7972 PointF touchedPoint = {10, 10};
7973 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007974 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007975
7976 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007977 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007978
7979 // Touch Window 2
7980 touchedPoint = {150, 150};
7981 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007982 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007983}
7984
chaviw9eaa22c2020-07-01 16:21:27 -07007985TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
7986 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07007987 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007988 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07007989
7990 // Touch Window 1
7991 PointF touchedPoint = {10, 10};
7992 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007993 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007994 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007995 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07007996
7997 // Touch Window 2
7998 touchedPoint = {150, 150};
7999 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008000 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
8001 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008002
chaviw9eaa22c2020-07-01 16:21:27 -07008003 // Update the transform so rotation is set
8004 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008005 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008006 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008007 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07008008}
8009
chaviw9eaa22c2020-07-01 16:21:27 -07008010TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008011 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008012 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008013
8014 // Touch Window 1
8015 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8016 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008017 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008018
8019 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008020 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
8021 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
8022 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07008023 touchedPoints.push_back(PointF{150, 150});
8024 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008025 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008026
chaviw9eaa22c2020-07-01 16:21:27 -07008027 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008028 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008029 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008030
chaviw9eaa22c2020-07-01 16:21:27 -07008031 // Update the transform so rotation is set for Window 2
8032 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008033 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008034 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008035 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008036}
8037
chaviw9eaa22c2020-07-01 16:21:27 -07008038TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008039 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008040 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008041
8042 // Touch Window 1
8043 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8044 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008045 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008046
8047 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008048 touchedPoints.push_back(PointF{150, 150});
8049 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008050
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008051 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008052
8053 // Move both windows
8054 touchedPoints = {{20, 20}, {175, 175}};
8055 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8056 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8057
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008058 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008059
chaviw9eaa22c2020-07-01 16:21:27 -07008060 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008061 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008062 expectedPoints.pop_back();
8063
8064 // Touch Window 2
8065 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008066 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07008067 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008068 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07008069
8070 // Move both windows
8071 touchedPoints = {{20, 20}, {175, 175}};
8072 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8073 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8074
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008075 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008076}
8077
8078TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
8079 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008080 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008081
8082 // Touch Window 1
8083 std::vector<PointF> touchedPoints = {PointF{10, 10}};
8084 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008085 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008086
8087 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07008088 touchedPoints.push_back(PointF{150, 150});
8089 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008090
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008091 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008092
8093 // Move both windows
8094 touchedPoints = {{20, 20}, {175, 175}};
8095 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
8096 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
8097
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008098 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00008099}
8100
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008101/**
8102 * When one of the windows is slippery, the touch should not slip into the other window with the
8103 * same input channel.
8104 */
8105TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
8106 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008107 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07008108
8109 // Touch down in window 1
8110 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
8111 ADISPLAY_ID_DEFAULT, {{50, 50}}));
8112 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
8113
8114 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
8115 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
8116 // getting generated.
8117 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
8118 ADISPLAY_ID_DEFAULT, {{150, 150}}));
8119
8120 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
8121}
8122
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008123/**
8124 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
8125 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
8126 * that the pointer is hovering over may have a different transform.
8127 */
8128TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008129 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008130
8131 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008132 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
8133 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8134 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008135 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
8136 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008137 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008138 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8139 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
8140 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008141 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00008142 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07008143 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
8144}
8145
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008146class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
8147 virtual void SetUp() override {
8148 InputDispatcherTest::SetUp();
8149
Chris Yea209fde2020-07-22 13:54:51 -07008150 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008151 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008152 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
8153 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008154 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008155 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07008156 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008157
8158 // Set focused application.
8159 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8160
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008161 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008162 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008163 mWindow->consumeFocusEvent(true);
8164 }
8165
8166 virtual void TearDown() override {
8167 InputDispatcherTest::TearDown();
8168 mWindow.clear();
8169 }
8170
8171protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008172 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07008173 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008174 sp<FakeWindowHandle> mWindow;
8175 static constexpr PointF WINDOW_LOCATION = {20, 20};
8176
8177 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008178 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
8179 .x(WINDOW_LOCATION.x)
8180 .y(WINDOW_LOCATION.y);
8181 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8182 .pointer(touchingPointer)
8183 .build());
8184 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8185 .pointer(touchingPointer)
8186 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008187 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008188
8189 sp<FakeWindowHandle> addSpyWindow() {
8190 sp<FakeWindowHandle> spy =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008191 sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008192 spy->setTrustedOverlay(true);
8193 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08008194 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008195 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008196 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008197 return spy;
8198 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008199};
8200
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008201// Send a tap and respond, which should not cause an ANR.
8202TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
8203 tapOnWindow();
8204 mWindow->consumeMotionDown();
8205 mWindow->consumeMotionUp();
8206 ASSERT_TRUE(mDispatcher->waitForIdle());
8207 mFakePolicy->assertNotifyAnrWasNotCalled();
8208}
8209
8210// Send a regular key and respond, which should not cause an ANR.
8211TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008212 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008213 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
8214 ASSERT_TRUE(mDispatcher->waitForIdle());
8215 mFakePolicy->assertNotifyAnrWasNotCalled();
8216}
8217
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008218TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
8219 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008220 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008221 mWindow->consumeFocusEvent(false);
8222
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008223 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008224 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8225 InputEventInjectionSync::NONE, CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00008226 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008227 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05008228 // Key will not go to window because we have no focused window.
8229 // The 'no focused window' ANR timer should start instead.
8230
8231 // Now, the focused application goes away.
8232 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, nullptr);
8233 // The key should get dropped and there should be no ANR.
8234
8235 ASSERT_TRUE(mDispatcher->waitForIdle());
8236 mFakePolicy->assertNotifyAnrWasNotCalled();
8237}
8238
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008239// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008240// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8241// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008242TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008244 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008245 WINDOW_LOCATION));
8246
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008247 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008248 ASSERT_TRUE(sequenceNum);
8249 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008250 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008251
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008252 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008253 mWindow->consumeMotionEvent(
8254 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008255 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008256 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008257}
8258
8259// Send a key to the app and have the app not respond right away.
8260TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
8261 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008263 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008264 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008265 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008266 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07008267 ASSERT_TRUE(mDispatcher->waitForIdle());
8268}
8269
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008270// We have a focused application, but no focused window
8271TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008272 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008273 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008274 mWindow->consumeFocusEvent(false);
8275
8276 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008278 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008279 WINDOW_LOCATION));
8280 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
8281 mDispatcher->waitForIdle();
8282 mFakePolicy->assertNotifyAnrWasNotCalled();
8283
8284 // Once a focused event arrives, we get an ANR for this application
8285 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8286 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008287 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008288 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008289 InputEventInjectionSync::WAIT_FOR_RESULT, 50ms, /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008290 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008291 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07008292 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008293 ASSERT_TRUE(mDispatcher->waitForIdle());
8294}
8295
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008296/**
8297 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
8298 * there will not be an ANR.
8299 */
8300TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
8301 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008302 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008303 mWindow->consumeFocusEvent(false);
8304
8305 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07008306 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
8307 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008308 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
8309 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
8310
8311 // Define a valid key down event that is stale (too old).
8312 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
Harry Cutts101ee9b2023-07-06 18:04:14 +00008313 INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /*flags=*/0, AKEYCODE_A, KEY_A,
Hu Guofe3c8f12023-09-22 17:20:15 +08008314 AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008315
Hu Guofe3c8f12023-09-22 17:20:15 +08008316 const int32_t policyFlags =
8317 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008318
8319 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00008320 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08008321 InputEventInjectionSync::WAIT_FOR_RESULT,
8322 INJECT_EVENT_TIMEOUT, policyFlags);
8323 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
8324 << "Injection should fail because the event is stale";
8325
8326 ASSERT_TRUE(mDispatcher->waitForIdle());
8327 mFakePolicy->assertNotifyAnrWasNotCalled();
8328 mWindow->assertNoEvents();
8329}
8330
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008331// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008332// Make sure that we don't notify policy twice about the same ANR.
8333TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008334 const std::chrono::duration appTimeout = 400ms;
8335 mApplication->setDispatchingTimeout(appTimeout);
8336 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
8337
Vishnu Nair47074b82020-08-14 11:54:47 -07008338 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008339 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008340 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008341
8342 // Once a focused event arrives, we get an ANR for this application
8343 // We specify the injection timeout to be smaller than the application timeout, to ensure that
8344 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008345 const std::chrono::duration eventInjectionTimeout = 100ms;
8346 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008347 const InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008348 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07008349 InputEventInjectionSync::WAIT_FOR_RESULT, eventInjectionTimeout,
8350 /*allowKeyRepeat=*/false);
8351 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
8352 << "result=" << ftl::enum_string(result);
8353 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
8354 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
8355 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
8356 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008357
Vishnu Naire4df8752022-09-08 09:17:55 -07008358 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008359 // ANR should not be raised again. It is up to policy to do that if it desires.
8360 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008361
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008362 // If we now get a focused window, the ANR should stop, but the policy handles that via
8363 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008364 ASSERT_TRUE(mDispatcher->waitForIdle());
8365}
8366
8367// We have a focused application, but no focused window
8368TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07008369 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008370 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008371 mWindow->consumeFocusEvent(false);
8372
8373 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008374 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008375
Vishnu Naire4df8752022-09-08 09:17:55 -07008376 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8377 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008378
8379 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008380 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008381 ASSERT_TRUE(mDispatcher->waitForIdle());
8382 mWindow->assertNoEvents();
8383}
8384
8385/**
8386 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
8387 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
8388 * If we process 1 of the events, but ANR on the second event with the same timestamp,
8389 * the ANR mechanism should still work.
8390 *
8391 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
8392 * DOWN event, while not responding on the second one.
8393 */
8394TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
8395 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008396 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008397 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8398 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8399 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008400 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008401
8402 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008403 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008404 ADISPLAY_ID_DEFAULT, WINDOW_LOCATION,
8405 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
8406 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008407 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008408
8409 // We have now sent down and up. Let's consume first event and then ANR on the second.
8410 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8411 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008412 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008413}
8414
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008415// A spy window can receive an ANR
8416TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
8417 sp<FakeWindowHandle> spy = addSpyWindow();
8418
8419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008420 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008421 WINDOW_LOCATION));
8422 mWindow->consumeMotionDown();
8423
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008424 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008425 ASSERT_TRUE(sequenceNum);
8426 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008427 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008428
8429 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008430 spy->consumeMotionEvent(
8431 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008432 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008433 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008434}
8435
8436// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008437// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008438TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
8439 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008440
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008442 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008443 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008445
8446 // Stuck on the ACTION_UP
8447 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008448 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008449
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008450 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008451 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008452 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8453 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008454
8455 mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8456 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008457 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008458 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008459 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008460}
8461
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008462// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008463// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008464TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
8465 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008466
8467 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008468 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8469 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008470
8471 mWindow->consumeMotionDown();
8472 // Stuck on the ACTION_UP
8473 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008474 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008475
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008476 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008477 tapOnWindow();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008478 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8479 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008480
8481 mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion
8482 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008483 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008484 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008485 spy->assertNoEvents();
8486}
8487
8488TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008489 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008490
Prabir Pradhanfb549072023-10-05 19:17:36 +00008491 FakeMonitorReceiver monitor = FakeMonitorReceiver(*mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008492
8493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008494 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008495 WINDOW_LOCATION));
8496
8497 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
8498 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
8499 ASSERT_TRUE(consumeSeq);
8500
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008501 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
8502 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08008503
8504 monitor.finishEvent(*consumeSeq);
8505 monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
8506
8507 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008508 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008509}
8510
8511// If a window is unresponsive, then you get anr. if the window later catches up and starts to
8512// process events, you don't get an anr. When the window later becomes unresponsive again, you
8513// get an ANR again.
8514// 1. tap -> block on ACTION_UP -> receive ANR
8515// 2. consume all pending events (= queue becomes healthy again)
8516// 3. tap again -> block on ACTION_UP again -> receive ANR second time
8517TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
8518 tapOnWindow();
8519
8520 mWindow->consumeMotionDown();
8521 // Block on ACTION_UP
8522 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008523 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008524 mWindow->consumeMotionUp(); // Now the connection should be healthy again
8525 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008526 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008527 mWindow->assertNoEvents();
8528
8529 tapOnWindow();
8530 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008531 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008532 mWindow->consumeMotionUp();
8533
8534 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008535 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008536 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008537 mWindow->assertNoEvents();
8538}
8539
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008540// If a connection remains unresponsive for a while, make sure policy is only notified once about
8541// it.
8542TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008545 WINDOW_LOCATION));
8546
8547 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008548 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008549 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008550 // 'notifyConnectionUnresponsive' should only be called once per connection
8551 mFakePolicy->assertNotifyAnrWasNotCalled();
8552 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008553 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08008554 mWindow->consumeMotionEvent(
8555 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008556 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008557 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08008558 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008559 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008560}
8561
8562/**
8563 * 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 -07008564 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008565 */
8566TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008567 // The timeouts in this test are established by relying on the fact that the "key waiting for
8568 // events timeout" is equal to 500ms.
8569 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008570 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008571 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008572
8573 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008574 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008575 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008576 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008577 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008578
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008579 // Don't finish the events yet, and send a key
8580 mDispatcher->notifyKey(
8581 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8582 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8583 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008584 // Key will not be sent to the window, yet, because the window is still processing events
8585 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008586 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008587 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008588
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008589 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008590 // if we wait long enough though, dispatcher will give up, and still send the key
8591 // to the focused window, even though we have not yet finished the motion event
8592 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
8593 mWindow->finishEvent(*downSequenceNum);
8594 mWindow->finishEvent(*upSequenceNum);
8595}
8596
8597/**
8598 * If a window is processing a motion event, and then a key event comes in, the key event should
8599 * not go to the focused window until the motion is processed.
8600 * If then a new motion comes in, then the pending key event should be going to the currently
8601 * focused window right away.
8602 */
8603TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008604 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
8605 // The timeouts in this test are established by relying on the fact that the "key waiting for
8606 // events timeout" is equal to 500ms.
8607 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008608 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008609 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008610
8611 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008612 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008613 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008614 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008615 ASSERT_TRUE(upSequenceNum);
8616 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008617 mDispatcher->notifyKey(
8618 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8619 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8620 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008621 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008622 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008623
8624 // Now tap down again. It should cause the pending key to go to the focused window right away.
8625 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08008626 // Now that we tapped, we should receive the key immediately.
8627 // Since there's still room for slowness, we use 200ms, which is much less than
8628 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
8629 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
8630 ASSERT_NE(nullptr, keyEvent);
8631 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
8632 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
8633 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
8634 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008635 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
8636 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08008637 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8638 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008639 mWindow->assertNoEvents();
8640}
8641
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008642/**
8643 * Send an event to the app and have the app not respond right away.
8644 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
8645 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
8646 * At some point, the window becomes responsive again.
8647 * Ensure that subsequent events get dropped, and the next gesture is delivered.
8648 */
8649TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
8650 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8651 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
8652 .build());
8653
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008654 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07008655 ASSERT_TRUE(sequenceNum);
8656 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8657 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8658
8659 mWindow->finishEvent(*sequenceNum);
8660 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8661 ASSERT_TRUE(mDispatcher->waitForIdle());
8662 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
8663
8664 // Now that the window is responsive, let's continue the gesture.
8665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8666 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8667 .build());
8668
8669 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8670 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8671 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8672 .build());
8673
8674 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
8675 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8676 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
8677 .build());
8678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8679 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
8680 .build());
8681 // We already canceled this pointer, so the window shouldn't get any new events.
8682 mWindow->assertNoEvents();
8683
8684 // Start another one.
8685 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8686 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
8687 .build());
8688 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8689}
8690
Prabir Pradhanfc364722024-02-08 17:51:20 +00008691// Send an event to the app and have the app not respond right away. Then remove the app window.
8692// When the window is removed, the dispatcher will cancel the events for that window.
8693// So InputDispatcher will enqueue ACTION_CANCEL event as well.
8694TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
8695 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8696 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8697 {WINDOW_LOCATION}));
8698
8699 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
8700 ASSERT_TRUE(sequenceNum);
8701
8702 // Remove the window, but the input channel should remain alive.
8703 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8704
8705 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8706 // Since the window was removed, Dispatcher does not know the PID associated with the window
8707 // anymore, so the policy is notified without the PID.
8708 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
8709 /*pid=*/std::nullopt);
8710
8711 mWindow->finishEvent(*sequenceNum);
8712 // The cancellation was generated when the window was removed, along with the focus event.
8713 mWindow->consumeMotionEvent(
8714 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
8715 mWindow->consumeFocusEvent(false);
8716 ASSERT_TRUE(mDispatcher->waitForIdle());
8717 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
8718}
8719
8720// Send an event to the app and have the app not respond right away. Wait for the policy to be
8721// notified of the unresponsive window, then remove the app window.
8722TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
8723 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
8724 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
8725 {WINDOW_LOCATION}));
8726
8727 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
8728 ASSERT_TRUE(sequenceNum);
8729 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
8730 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
8731
8732 // Remove the window, but the input channel should remain alive.
8733 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8734
8735 mWindow->finishEvent(*sequenceNum);
8736 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
8737 mWindow->consumeMotionEvent(
8738 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
8739 mWindow->consumeFocusEvent(false);
8740 ASSERT_TRUE(mDispatcher->waitForIdle());
8741 // Since the window was removed, Dispatcher does not know the PID associated with the window
8742 // becoming responsive, so the policy is notified without the PID.
8743 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
8744}
8745
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008746class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
8747 virtual void SetUp() override {
8748 InputDispatcherTest::SetUp();
8749
Chris Yea209fde2020-07-22 13:54:51 -07008750 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008751 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008752 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
8753 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008754 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008755 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008756 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008757
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008758 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
8759 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008760 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008761 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008762
8763 // Set focused application.
8764 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -07008765 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008766
8767 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008768 mDispatcher->onWindowInfosChanged(
8769 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008770 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008771 mFocusedWindow->consumeFocusEvent(true);
8772 }
8773
8774 virtual void TearDown() override {
8775 InputDispatcherTest::TearDown();
8776
8777 mUnfocusedWindow.clear();
8778 mFocusedWindow.clear();
8779 }
8780
8781protected:
Chris Yea209fde2020-07-22 13:54:51 -07008782 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008783 sp<FakeWindowHandle> mUnfocusedWindow;
8784 sp<FakeWindowHandle> mFocusedWindow;
8785 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
8786 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
8787 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
8788
8789 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
8790
8791 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
8792
8793private:
8794 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008796 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008797 location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008799 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008800 location));
8801 }
8802};
8803
8804// If we have 2 windows that are both unresponsive, the one with the shortest timeout
8805// should be ANR'd first.
8806TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008808 injectMotionEvent(*mDispatcher,
8809 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8810 AINPUT_SOURCE_TOUCHSCREEN)
8811 .pointer(PointerBuilder(0, ToolType::FINGER)
8812 .x(FOCUSED_WINDOW_LOCATION.x)
8813 .y(FOCUSED_WINDOW_LOCATION.y))
8814 .build()));
8815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8816 injectMotionEvent(*mDispatcher,
8817 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
8818 AINPUT_SOURCE_TOUCHSCREEN)
8819 .pointer(PointerBuilder(0, ToolType::FINGER)
8820 .x(FOCUSED_WINDOW_LOCATION.x)
8821 .y(FOCUSED_WINDOW_LOCATION.y))
8822 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008823 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008824 mFocusedWindow->consumeMotionUp();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008825 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008826 // We consumed all events, so no ANR
8827 ASSERT_TRUE(mDispatcher->waitForIdle());
8828 mFakePolicy->assertNotifyAnrWasNotCalled();
8829
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008830 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008831 injectMotionEvent(*mDispatcher,
8832 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
8833 AINPUT_SOURCE_TOUCHSCREEN)
8834 .pointer(PointerBuilder(0, ToolType::FINGER)
8835 .x(FOCUSED_WINDOW_LOCATION.x)
8836 .y(FOCUSED_WINDOW_LOCATION.y))
8837 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008838 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008839 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008840
8841 const std::chrono::duration timeout =
8842 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008843 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07008844
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008845 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008846 mFocusedWindow->consumeMotionDown();
8847 // This cancel is generated because the connection was unresponsive
8848 mFocusedWindow->consumeMotionCancel();
8849 mFocusedWindow->assertNoEvents();
8850 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008851 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08008852 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8853 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008854 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008855}
8856
8857// If we have 2 windows with identical timeouts that are both unresponsive,
8858// it doesn't matter which order they should have ANR.
8859// But we should receive ANR for both.
8860TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
8861 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008862 mUnfocusedWindow->setDispatchingTimeout(
8863 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008864 mDispatcher->onWindowInfosChanged(
8865 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008866
8867 tapOnFocusedWindow();
8868 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008869 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008870 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
8871 mFocusedWindow->getDispatchingTimeout(
8872 DISPATCHING_TIMEOUT)),
8873 mFakePolicy->getUnresponsiveWindowToken(0ms)};
8874
8875 ASSERT_THAT(anrConnectionTokens,
8876 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8877 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008878
8879 ASSERT_TRUE(mDispatcher->waitForIdle());
8880 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008881
8882 mFocusedWindow->consumeMotionDown();
8883 mFocusedWindow->consumeMotionUp();
8884 mUnfocusedWindow->consumeMotionOutside();
8885
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008886 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
8887 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008888
8889 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07008890 ASSERT_THAT(responsiveTokens,
8891 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
8892 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008893 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008894}
8895
8896// If a window is already not responding, the second tap on the same window should be ignored.
8897// We should also log an error to account for the dropped event (not tested here).
8898// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
8899TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
8900 tapOnFocusedWindow();
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00008901 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008902 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008903 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008904 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008905 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008906 ASSERT_TRUE(upEventSequenceNum);
8907 const std::chrono::duration timeout =
8908 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08008909 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008910
8911 // Tap once again
8912 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008913 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008914 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008915 FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008916 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008917 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008918 FOCUSED_WINDOW_LOCATION));
8919 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
8920 // valid touch target
8921 mUnfocusedWindow->assertNoEvents();
8922
8923 // Consume the first tap
8924 mFocusedWindow->finishEvent(*downEventSequenceNum);
8925 mFocusedWindow->finishEvent(*upEventSequenceNum);
8926 ASSERT_TRUE(mDispatcher->waitForIdle());
8927 // The second tap did not go to the focused window
8928 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05008929 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -08008930 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
8931 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008932 mFakePolicy->assertNotifyAnrWasNotCalled();
8933}
8934
8935// If you tap outside of all windows, there will not be ANR
8936TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008937 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008938 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008939 LOCATION_OUTSIDE_ALL_WINDOWS));
8940 ASSERT_TRUE(mDispatcher->waitForIdle());
8941 mFakePolicy->assertNotifyAnrWasNotCalled();
8942}
8943
8944// Since the focused window is paused, tapping on it should not produce any events
8945TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
8946 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008947 mDispatcher->onWindowInfosChanged(
8948 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008949
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008950 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008951 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008952 FOCUSED_WINDOW_LOCATION));
8953
8954 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
8955 ASSERT_TRUE(mDispatcher->waitForIdle());
8956 // Should not ANR because the window is paused, and touches shouldn't go to it
8957 mFakePolicy->assertNotifyAnrWasNotCalled();
8958
8959 mFocusedWindow->assertNoEvents();
8960 mUnfocusedWindow->assertNoEvents();
8961}
8962
8963/**
8964 * 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 -07008965 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008966 * If a different window becomes focused at this time, the key should go to that window instead.
8967 *
8968 * Warning!!!
8969 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
8970 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008971 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008972 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
8973 *
8974 * If that value changes, this test should also change.
8975 */
8976TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
8977 // Set a long ANR timeout to prevent it from triggering
8978 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008979 mDispatcher->onWindowInfosChanged(
8980 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008981
8982 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008983 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008984 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008985 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008986 ASSERT_TRUE(upSequenceNum);
8987 // Don't finish the events yet, and send a key
8988 // Injection will succeed because we will eventually give up and send the key to the focused
8989 // window even if motions are still being processed.
8990
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008991 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008992 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
8993 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07008995 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008996 // and the key remains pending, waiting for the touch events to be processed.
8997 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
8998 // under the hood.
8999 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
9000 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009001
9002 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -07009003 mFocusedWindow->setFocusable(false);
9004 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009005 mDispatcher->onWindowInfosChanged(
9006 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009007 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009008
9009 // Focus events should precede the key events
9010 mUnfocusedWindow->consumeFocusEvent(true);
9011 mFocusedWindow->consumeFocusEvent(false);
9012
9013 // Finish the tap events, which should unblock dispatcher
9014 mUnfocusedWindow->finishEvent(*downSequenceNum);
9015 mUnfocusedWindow->finishEvent(*upSequenceNum);
9016
9017 // Now that all queues are cleared and no backlog in the connections, the key event
9018 // can finally go to the newly focused "mUnfocusedWindow".
9019 mUnfocusedWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9020 mFocusedWindow->assertNoEvents();
9021 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009022 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009023}
9024
9025// When the touch stream is split across 2 windows, and one of them does not respond,
9026// then ANR should be raised and the touch should be canceled for the unresponsive window.
9027// The other window should not be affected by that.
9028TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
9029 // Touch Window 1
Prabir Pradhan678438e2023-04-13 19:32:51 +00009030 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9031 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9032 {FOCUSED_WINDOW_LOCATION}));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009033 mUnfocusedWindow->consumeMotionOutside(ADISPLAY_ID_DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009034
9035 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +00009036 mDispatcher->notifyMotion(
9037 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9038 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009039
9040 const std::chrono::duration timeout =
9041 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009042 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009043
9044 mUnfocusedWindow->consumeMotionDown();
9045 mFocusedWindow->consumeMotionDown();
9046 // Focused window may or may not receive ACTION_MOVE
9047 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009048 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009049 ASSERT_TRUE(moveOrCancelSequenceNum);
9050 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
9051 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -07009052 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009053 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
9054 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
9055 mFocusedWindow->consumeMotionCancel();
9056 } else {
9057 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
9058 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009059 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009060 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
9061 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009062
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009063 mUnfocusedWindow->assertNoEvents();
9064 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009065 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009066}
9067
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009068/**
9069 * If we have no focused window, and a key comes in, we start the ANR timer.
9070 * The focused application should add a focused window before the timer runs out to prevent ANR.
9071 *
9072 * If the user touches another application during this time, the key should be dropped.
9073 * Next, if a new focused window comes in, without toggling the focused application,
9074 * then no ANR should occur.
9075 *
9076 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
9077 * but in some cases the policy may not update the focused application.
9078 */
9079TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
9080 std::shared_ptr<FakeApplicationHandle> focusedApplication =
9081 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -07009082 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009083 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, focusedApplication);
9084 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
9085 mFocusedWindow->setFocusable(false);
9086
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009087 mDispatcher->onWindowInfosChanged(
9088 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009089 mFocusedWindow->consumeFocusEvent(false);
9090
9091 // Send a key. The ANR timer should start because there is no focused window.
9092 // 'focusedApplication' will get blamed if this timer completes.
9093 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009094 InputEventInjectionResult result =
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009095 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9096 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +00009097 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009099
9100 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
9101 // then the injected touches won't cause the focused event to get dropped.
9102 // The dispatcher only checks for whether the queue should be pruned upon queueing.
9103 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
9104 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
9105 // For this test, it means that the key would get delivered to the window once it becomes
9106 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009107 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009108
9109 // Touch unfocused window. This should force the pending key to get dropped.
Prabir Pradhan678438e2023-04-13 19:32:51 +00009110 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9111 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9112 {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009113
9114 // We do not consume the motion right away, because that would require dispatcher to first
9115 // process (== drop) the key event, and by that time, ANR will be raised.
9116 // Set the focused window first.
9117 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009118 mDispatcher->onWindowInfosChanged(
9119 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -05009120 setFocusedWindow(mFocusedWindow);
9121 mFocusedWindow->consumeFocusEvent(true);
9122 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
9123 // to another application. This could be a bug / behaviour in the policy.
9124
9125 mUnfocusedWindow->consumeMotionDown();
9126
9127 ASSERT_TRUE(mDispatcher->waitForIdle());
9128 // Should not ANR because we actually have a focused window. It was just added too slowly.
9129 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
9130}
9131
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -08009132/**
9133 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
9134 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
9135 * dispatcher doesn't prune pointer events incorrectly.
9136 *
9137 * This test reproduces a crash in InputDispatcher.
9138 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
9139 *
9140 * Keep the currently focused application (mApplication), and have no focused window.
9141 * We set up two additional windows:
9142 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
9143 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
9144 * window. This window is not focusable, but is touchable.
9145 *
9146 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
9147 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
9148 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
9149 *
9150 * Now, we touch "Another window". This window is owned by a different application than
9151 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
9152 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
9153 * dropping the events from its queue. Ensure that no crash occurs.
9154 *
9155 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
9156 * This does not affect the test running time.
9157 */
9158TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
9159 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
9160 std::make_shared<FakeApplicationHandle>();
9161 systemUiApplication->setDispatchingTimeout(3000ms);
9162 mFakePolicy->setStaleEventTimeout(3000ms);
9163 sp<FakeWindowHandle> navigationBar =
9164 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
9165 ADISPLAY_ID_DEFAULT);
9166 navigationBar->setFocusable(false);
9167 navigationBar->setWatchOutsideTouch(true);
9168 navigationBar->setFrame(Rect(0, 0, 100, 100));
9169
9170 mApplication->setDispatchingTimeout(3000ms);
9171 // 'mApplication' is already focused, but we call it again here to make it explicit.
9172 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApplication);
9173
9174 std::shared_ptr<FakeApplicationHandle> anotherApplication =
9175 std::make_shared<FakeApplicationHandle>();
9176 sp<FakeWindowHandle> appWindow =
9177 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
9178 ADISPLAY_ID_DEFAULT);
9179 appWindow->setFocusable(false);
9180 appWindow->setFrame(Rect(100, 100, 200, 200));
9181
9182 mDispatcher->onWindowInfosChanged(
9183 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
9184 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
9185 mFocusedWindow->consumeFocusEvent(false);
9186
9187 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
9188 // in response.
9189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9190 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9191 .build());
9192 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9193
9194 // Key will not be sent anywhere because we have no focused window. It will remain pending.
9195 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
9196 InputEventInjectionResult result =
9197 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9198 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9199 /*allowKeyRepeat=*/false);
9200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9201
9202 // Finish the gesture - lift up finger and inject ACTION_UP key event
9203 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9204 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9205 .build());
9206 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, ADISPLAY_ID_DEFAULT,
9207 InputEventInjectionSync::NONE, /*injectionTimeout=*/100ms,
9208 /*allowKeyRepeat=*/false);
9209 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
9210 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
9211 // getting any events yet.
9212 navigationBar->assertNoEvents();
9213
9214 // Now touch "Another window". This touch is going to a different application than the one we
9215 // are waiting for (which is 'mApplication').
9216 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
9217 // trying to be injected) and to continue processing the rest of the events in the original
9218 // order.
9219 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9220 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9221 .build());
9222 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
9223 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
9224 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
9225
9226 appWindow->assertNoEvents();
9227 navigationBar->assertNoEvents();
9228}
9229
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009230// These tests ensure we cannot send touch events to a window that's positioned behind a window
9231// that has feature NO_INPUT_CHANNEL.
9232// Layout:
9233// Top (closest to user)
9234// mNoInputWindow (above all windows)
9235// mBottomWindow
9236// Bottom (furthest from user)
9237class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
9238 virtual void SetUp() override {
9239 InputDispatcherTest::SetUp();
9240
9241 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009242 mNoInputWindow =
9243 sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9244 "Window without input channel", ADISPLAY_ID_DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009245 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009246 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009247 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
9248 // It's perfectly valid for this window to not have an associated input channel
9249
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009250 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
9251 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009252 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
9253
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009254 mDispatcher->onWindowInfosChanged(
9255 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009256 }
9257
9258protected:
9259 std::shared_ptr<FakeApplicationHandle> mApplication;
9260 sp<FakeWindowHandle> mNoInputWindow;
9261 sp<FakeWindowHandle> mBottomWindow;
9262};
9263
9264TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
9265 PointF touchedPoint = {10, 10};
9266
Prabir Pradhan678438e2023-04-13 19:32:51 +00009267 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9268 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9269 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009270
9271 mNoInputWindow->assertNoEvents();
9272 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
9273 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
9274 // and therefore should prevent mBottomWindow from receiving touches
9275 mBottomWindow->assertNoEvents();
9276}
9277
9278/**
9279 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
9280 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
9281 */
9282TEST_F(InputDispatcherMultiWindowOcclusionTests,
9283 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009284 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
9285 "Window with input channel and NO_INPUT_CHANNEL",
9286 ADISPLAY_ID_DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009287
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009288 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009289 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009290 mDispatcher->onWindowInfosChanged(
9291 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009292
9293 PointF touchedPoint = {10, 10};
9294
Prabir Pradhan678438e2023-04-13 19:32:51 +00009295 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9296 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9297 {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -05009298
9299 mNoInputWindow->assertNoEvents();
9300 mBottomWindow->assertNoEvents();
9301}
9302
Vishnu Nair958da932020-08-21 17:12:37 -07009303class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
9304protected:
9305 std::shared_ptr<FakeApplicationHandle> mApp;
9306 sp<FakeWindowHandle> mWindow;
9307 sp<FakeWindowHandle> mMirror;
9308
9309 virtual void SetUp() override {
9310 InputDispatcherTest::SetUp();
9311 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009312 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00009313 mMirror = mWindow->clone(ADISPLAY_ID_DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009314 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
9315 mWindow->setFocusable(true);
9316 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009317 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009318 }
9319};
9320
9321TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
9322 // Request focus on a mirrored window
9323 setFocusedWindow(mMirror);
9324
9325 // window gets focused
9326 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009327 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009328 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009329 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
9330}
9331
9332// A focused & mirrored window remains focused only if the window and its mirror are both
9333// focusable.
9334TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
9335 setFocusedWindow(mMirror);
9336
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009337 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -07009338 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009339 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009340 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009341 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009342 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009343 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009344 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9345
9346 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009347 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009348
9349 // window loses focus since one of the windows associated with the token in not focusable
9350 mWindow->consumeFocusEvent(false);
9351
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009352 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009353 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009354 mWindow->assertNoEvents();
9355}
9356
9357// A focused & mirrored window remains focused until the window and its mirror both become
9358// invisible.
9359TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
9360 setFocusedWindow(mMirror);
9361
9362 // window gets focused
9363 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009364 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009365 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009366 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009367 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009368 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009369 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9370
9371 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009372 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009373
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009375 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009376 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009377 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009378 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009379 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9380
9381 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009382 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009383
9384 // window loses focus only after all windows associated with the token become invisible.
9385 mWindow->consumeFocusEvent(false);
9386
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009387 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009388 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009389 mWindow->assertNoEvents();
9390}
9391
9392// A focused & mirrored window remains focused until both windows are removed.
9393TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
9394 setFocusedWindow(mMirror);
9395
9396 // window gets focused
9397 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009398 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009399 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009400 mWindow->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009402 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009403 mWindow->consumeKeyUp(ADISPLAY_ID_NONE);
9404
9405 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009406 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009407
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009408 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009409 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009410 mMirror->consumeKeyDown(ADISPLAY_ID_NONE);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009412 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009413 mMirror->consumeKeyUp(ADISPLAY_ID_NONE);
Vishnu Nair958da932020-08-21 17:12:37 -07009414
9415 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009416 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009417 mWindow->consumeFocusEvent(false);
9418
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009419 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009420 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -07009421 mWindow->assertNoEvents();
9422}
9423
9424// Focus request can be pending until one window becomes visible.
9425TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
9426 // Request focus on an invisible mirror.
9427 mWindow->setVisible(false);
9428 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009429 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009430 setFocusedWindow(mMirror);
9431
9432 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009433 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009434 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9435 ADISPLAY_ID_DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07009436
9437 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009438 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009439
9440 // window gets focused
9441 mWindow->consumeFocusEvent(true);
9442 // window gets the pending key event
9443 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
9444}
Prabir Pradhan99987712020-11-10 18:43:05 -08009445
9446class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
9447protected:
9448 std::shared_ptr<FakeApplicationHandle> mApp;
9449 sp<FakeWindowHandle> mWindow;
9450 sp<FakeWindowHandle> mSecondWindow;
9451
9452 void SetUp() override {
9453 InputDispatcherTest::SetUp();
9454 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009455 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009456 mWindow->setFocusable(true);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009457 mSecondWindow =
9458 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -08009459 mSecondWindow->setFocusable(true);
9460
9461 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009462 mDispatcher->onWindowInfosChanged(
9463 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -08009464
9465 setFocusedWindow(mWindow);
9466 mWindow->consumeFocusEvent(true);
9467 }
9468
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009469 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009470 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -08009471 }
9472
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009473 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
9474 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -08009475 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +09009476 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009477 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009478 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009479 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -08009480 }
9481};
9482
9483TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
9484 // Ensure that capture cannot be obtained for unfocused windows.
9485 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
9486 mFakePolicy->assertSetPointerCaptureNotCalled();
9487 mSecondWindow->assertNoEvents();
9488
9489 // Ensure that capture can be enabled from the focus window.
9490 requestAndVerifyPointerCapture(mWindow, true);
9491
9492 // Ensure that capture cannot be disabled from a window that does not have capture.
9493 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
9494 mFakePolicy->assertSetPointerCaptureNotCalled();
9495
9496 // Ensure that capture can be disabled from the window with capture.
9497 requestAndVerifyPointerCapture(mWindow, false);
9498}
9499
9500TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009501 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009502
9503 setFocusedWindow(mSecondWindow);
9504
9505 // Ensure that the capture disabled event was sent first.
9506 mWindow->consumeCaptureEvent(false);
9507 mWindow->consumeFocusEvent(false);
9508 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +09009509 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009510
9511 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009512 notifyPointerCaptureChanged({});
9513 notifyPointerCaptureChanged(request);
9514 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -08009515 mWindow->assertNoEvents();
9516 mSecondWindow->assertNoEvents();
9517 mFakePolicy->assertSetPointerCaptureNotCalled();
9518}
9519
9520TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009521 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -08009522
9523 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009524 notifyPointerCaptureChanged({});
9525 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -08009526
9527 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +09009528 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -08009529 mWindow->consumeCaptureEvent(false);
9530 mWindow->assertNoEvents();
9531}
9532
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009533TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
9534 requestAndVerifyPointerCapture(mWindow, true);
9535
9536 // The first window loses focus.
9537 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +09009538 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009539 mWindow->consumeCaptureEvent(false);
9540
9541 // Request Pointer Capture from the second window before the notification from InputReader
9542 // arrives.
9543 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009544 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009545
9546 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009547 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009548
9549 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009550 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -08009551
9552 mSecondWindow->consumeFocusEvent(true);
9553 mSecondWindow->consumeCaptureEvent(true);
9554}
9555
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009556TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
9557 // App repeatedly enables and disables capture.
9558 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009559 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009560 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +09009561 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009562 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009563 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +00009564
9565 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
9566 // first request is now stale, this should do nothing.
9567 notifyPointerCaptureChanged(firstRequest);
9568 mWindow->assertNoEvents();
9569
9570 // InputReader notifies that the second request was enabled.
9571 notifyPointerCaptureChanged(secondRequest);
9572 mWindow->consumeCaptureEvent(true);
9573}
9574
Prabir Pradhan7092e262022-05-03 16:51:09 +00009575TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
9576 requestAndVerifyPointerCapture(mWindow, true);
9577
9578 // App toggles pointer capture off and on.
9579 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +09009580 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +00009581
9582 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +09009583 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +00009584
9585 // InputReader notifies that the latest "enable" request was processed, while skipping over the
9586 // preceding "disable" request.
9587 notifyPointerCaptureChanged(enableRequest);
9588
9589 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
9590 // any notifications.
9591 mWindow->assertNoEvents();
9592}
9593
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009594/**
9595 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
9596 * mouse movements don't affect the previous mouse hovering state.
9597 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
9598 * HOVER_MOVE events).
9599 */
9600TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
9601 // Mouse hover on the window
9602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
9603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9604 .build());
9605 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9606 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
9607 .build());
9608
9609 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
9610 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
9611
9612 // Start pointer capture
9613 requestAndVerifyPointerCapture(mWindow, true);
9614
9615 // Send some relative mouse movements and receive them in the window.
9616 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
9617 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
9618 .build());
9619 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
9620 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
9621
9622 // Stop pointer capture
9623 requestAndVerifyPointerCapture(mWindow, false);
9624
9625 // Continue hovering on the window
9626 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
9627 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
9628 .build());
9629 mWindow->consumeMotionEvent(
9630 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
9631
9632 mWindow->assertNoEvents();
9633}
9634
Hiroki Sato25040232024-02-22 17:21:22 +09009635using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
9636
9637TEST_F(InputDispatcherPointerCaptureDeathTest,
9638 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
9639 testing::GTEST_FLAG(death_test_style) = "threadsafe";
9640 ScopedSilentDeath _silentDeath;
9641
9642 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
9643 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
9644
9645 // Dispatch a pointer changed event with a wrong token.
9646 request.window = mSecondWindow->getToken();
9647 ASSERT_DEATH(
9648 {
9649 notifyPointerCaptureChanged(request);
9650 mSecondWindow->consumeCaptureEvent(true);
9651 },
9652 "Unexpected requested window for Pointer Capture.");
9653}
9654
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009655class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
9656protected:
9657 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +00009658
9659 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
9660 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
9661
9662 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
9663 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9664
9665 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
9666 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
9667 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
9668 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
9669 MAXIMUM_OBSCURING_OPACITY);
9670
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009671 static constexpr gui::Uid TOUCHED_APP_UID{10001};
9672 static constexpr gui::Uid APP_B_UID{10002};
9673 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009674
9675 sp<FakeWindowHandle> mTouchWindow;
9676
9677 virtual void SetUp() override {
9678 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009679 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009680 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
9681 }
9682
9683 virtual void TearDown() override {
9684 InputDispatcherTest::TearDown();
9685 mTouchWindow.clear();
9686 }
9687
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009688 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -05009689 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009690 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009691 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009692 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009693 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009694 return window;
9695 }
9696
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00009697 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009698 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
9699 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009700 sp<FakeWindowHandle>::make(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009701 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00009702 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009703 return window;
9704 }
9705
9706 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009707 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9708 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9709 points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009710 }
9711};
9712
9713TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009714 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009715 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009716 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009717
9718 touch();
9719
9720 mTouchWindow->assertNoEvents();
9721}
9722
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009723TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +00009724 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
9725 const sp<FakeWindowHandle>& w =
9726 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009727 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +00009728
9729 touch();
9730
9731 mTouchWindow->assertNoEvents();
9732}
9733
9734TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009735 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
9736 const sp<FakeWindowHandle>& w =
9737 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009738 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009739
9740 touch();
9741
9742 w->assertNoEvents();
9743}
9744
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009745TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009746 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009747 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009748
9749 touch();
9750
9751 mTouchWindow->consumeAnyMotionDown();
9752}
9753
9754TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009755 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009756 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009757 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009758 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009759
9760 touch({PointF{100, 100}});
9761
9762 mTouchWindow->consumeAnyMotionDown();
9763}
9764
9765TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009766 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009767 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009768 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009769
9770 touch();
9771
9772 mTouchWindow->consumeAnyMotionDown();
9773}
9774
9775TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
9776 const sp<FakeWindowHandle>& w =
9777 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009778 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009779
9780 touch();
9781
9782 mTouchWindow->consumeAnyMotionDown();
9783}
9784
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009785TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
9786 const sp<FakeWindowHandle>& w =
9787 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009788 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009789
9790 touch();
9791
9792 w->assertNoEvents();
9793}
9794
9795/**
9796 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
9797 * inside) while letting them pass-through. Note that even though touch passes through the occluding
9798 * window, the occluding window will still receive ACTION_OUTSIDE event.
9799 */
9800TEST_F(InputDispatcherUntrustedTouchesTest,
9801 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
9802 const sp<FakeWindowHandle>& w =
9803 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009804 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009805 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009806
9807 touch();
9808
9809 w->consumeMotionOutside();
9810}
9811
9812TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
9813 const sp<FakeWindowHandle>& w =
9814 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08009815 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009816 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009817
9818 touch();
9819
Prabir Pradhandfabf8a2022-01-21 08:19:30 -08009820 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +00009821}
9822
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009823TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009824 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009825 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9826 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009827 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009828
9829 touch();
9830
9831 mTouchWindow->consumeAnyMotionDown();
9832}
9833
9834TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
9835 const sp<FakeWindowHandle>& w =
9836 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9837 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009838 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009839
9840 touch();
9841
9842 mTouchWindow->consumeAnyMotionDown();
9843}
9844
9845TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009846 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009847 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9848 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009849 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009850
9851 touch();
9852
9853 mTouchWindow->assertNoEvents();
9854}
9855
9856TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
9857 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
9858 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009859 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9860 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009861 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009862 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9863 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009864 mDispatcher->onWindowInfosChanged(
9865 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009866
9867 touch();
9868
9869 mTouchWindow->assertNoEvents();
9870}
9871
9872TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
9873 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
9874 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009875 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
9876 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009877 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009878 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
9879 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009880 mDispatcher->onWindowInfosChanged(
9881 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009882
9883 touch();
9884
9885 mTouchWindow->consumeAnyMotionDown();
9886}
9887
9888TEST_F(InputDispatcherUntrustedTouchesTest,
9889 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
9890 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009891 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9892 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009893 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009894 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9895 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009896 mDispatcher->onWindowInfosChanged(
9897 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009898
9899 touch();
9900
9901 mTouchWindow->consumeAnyMotionDown();
9902}
9903
9904TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
9905 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009906 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9907 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +00009908 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009909 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
9910 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009911 mDispatcher->onWindowInfosChanged(
9912 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +00009913
9914 touch();
9915
9916 mTouchWindow->assertNoEvents();
9917}
9918
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009919TEST_F(InputDispatcherUntrustedTouchesTest,
9920 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
9921 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009922 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9923 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009924 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009925 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9926 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009927 mDispatcher->onWindowInfosChanged(
9928 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009929
9930 touch();
9931
9932 mTouchWindow->assertNoEvents();
9933}
9934
9935TEST_F(InputDispatcherUntrustedTouchesTest,
9936 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
9937 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009938 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9939 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009940 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009941 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
9942 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009943 mDispatcher->onWindowInfosChanged(
9944 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009945
9946 touch();
9947
9948 mTouchWindow->consumeAnyMotionDown();
9949}
9950
9951TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
9952 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009953 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
9954 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009955 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009956
9957 touch();
9958
9959 mTouchWindow->consumeAnyMotionDown();
9960}
9961
9962TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
9963 const sp<FakeWindowHandle>& w =
9964 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009965 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +00009966
9967 touch();
9968
9969 mTouchWindow->consumeAnyMotionDown();
9970}
9971
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009972TEST_F(InputDispatcherUntrustedTouchesTest,
9973 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
9974 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9975 const sp<FakeWindowHandle>& w =
9976 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009977 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009978
9979 touch();
9980
9981 mTouchWindow->assertNoEvents();
9982}
9983
9984TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
9985 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
9986 const sp<FakeWindowHandle>& w =
9987 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009988 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +00009989
9990 touch();
9991
9992 mTouchWindow->consumeAnyMotionDown();
9993}
9994
9995TEST_F(InputDispatcherUntrustedTouchesTest,
9996 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
9997 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
9998 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +00009999 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10000 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010001 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010002
10003 touch();
10004
10005 mTouchWindow->consumeAnyMotionDown();
10006}
10007
10008TEST_F(InputDispatcherUntrustedTouchesTest,
10009 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
10010 const sp<FakeWindowHandle>& w1 =
10011 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10012 OPACITY_BELOW_THRESHOLD);
10013 const sp<FakeWindowHandle>& w2 =
10014 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
10015 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010016 mDispatcher->onWindowInfosChanged(
10017 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010018
10019 touch();
10020
10021 mTouchWindow->assertNoEvents();
10022}
10023
10024/**
10025 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
10026 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
10027 * (which alone would result in allowing touches) does not affect the blocking behavior.
10028 */
10029TEST_F(InputDispatcherUntrustedTouchesTest,
10030 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
10031 const sp<FakeWindowHandle>& wB =
10032 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
10033 OPACITY_BELOW_THRESHOLD);
10034 const sp<FakeWindowHandle>& wC =
10035 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
10036 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010037 mDispatcher->onWindowInfosChanged(
10038 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000010039
10040 touch();
10041
10042 mTouchWindow->assertNoEvents();
10043}
10044
10045/**
10046 * This test is testing that a window from a different UID but with same application token doesn't
10047 * block the touch. Apps can share the application token for close UI collaboration for example.
10048 */
10049TEST_F(InputDispatcherUntrustedTouchesTest,
10050 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
10051 const sp<FakeWindowHandle>& w =
10052 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
10053 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010054 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000010055
10056 touch();
10057
10058 mTouchWindow->consumeAnyMotionDown();
10059}
10060
arthurhungb89ccb02020-12-30 16:19:01 +080010061class InputDispatcherDragTests : public InputDispatcherTest {
10062protected:
10063 std::shared_ptr<FakeApplicationHandle> mApp;
10064 sp<FakeWindowHandle> mWindow;
10065 sp<FakeWindowHandle> mSecondWindow;
10066 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010067 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010068 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
10069 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080010070
10071 void SetUp() override {
10072 InputDispatcherTest::SetUp();
10073 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010074 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010075 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010076
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010077 mSecondWindow =
10078 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080010079 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080010080
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010081 mSpyWindow =
10082 sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010083 mSpyWindow->setSpy(true);
10084 mSpyWindow->setTrustedOverlay(true);
10085 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
10086
arthurhungb89ccb02020-12-30 16:19:01 +080010087 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010088 mDispatcher->onWindowInfosChanged(
10089 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
10090 {},
10091 0,
10092 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010093 }
10094
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010095 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
10096 switch (fromSource) {
10097 case AINPUT_SOURCE_TOUCHSCREEN:
10098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010099 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010100 ADISPLAY_ID_DEFAULT, {50, 50}))
10101 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10102 break;
10103 case AINPUT_SOURCE_STYLUS:
10104 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010105 injectMotionEvent(*mDispatcher,
10106 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10107 AINPUT_SOURCE_STYLUS)
10108 .buttonState(
10109 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
10110 .pointer(PointerBuilder(0, ToolType::STYLUS)
10111 .x(50)
10112 .y(50))
10113 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010114 break;
10115 case AINPUT_SOURCE_MOUSE:
10116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010117 injectMotionEvent(*mDispatcher,
10118 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10119 AINPUT_SOURCE_MOUSE)
10120 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
10121 .pointer(PointerBuilder(MOUSE_POINTER_ID,
10122 ToolType::MOUSE)
10123 .x(50)
10124 .y(50))
10125 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010126 break;
10127 default:
10128 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
10129 }
arthurhungb89ccb02020-12-30 16:19:01 +080010130
10131 // Window should receive motion event.
10132 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010133 // Spy window should also receive motion event
10134 mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010135 }
10136
10137 // Start performing drag, we will create a drag window and transfer touch to it.
10138 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
10139 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010140 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000010141 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010142 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000010143 }
arthurhungb89ccb02020-12-30 16:19:01 +080010144
10145 // The drag window covers the entire display
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010146 mDragWindow =
10147 sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010148 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010149 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
10150 *mWindow->getInfo(), *mSecondWindow->getInfo()},
10151 {},
10152 0,
10153 0});
arthurhungb89ccb02020-12-30 16:19:01 +080010154
10155 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000010156 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000010157 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
10158 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000010159 if (transferred) {
10160 mWindow->consumeMotionCancel();
Prabir Pradhan65455c72024-02-13 21:46:41 +000010161 mDragWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010162 }
10163 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080010164 }
10165};
10166
10167TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010168 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080010169
10170 // Move on window.
10171 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010172 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010173 ADISPLAY_ID_DEFAULT, {50, 50}))
10174 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010175 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010176 mWindow->consumeDragEvent(false, 50, 50);
10177 mSecondWindow->assertNoEvents();
10178
10179 // Move to another window.
10180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010181 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010182 ADISPLAY_ID_DEFAULT, {150, 50}))
10183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010184 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010185 mWindow->consumeDragEvent(true, 150, 50);
10186 mSecondWindow->consumeDragEvent(false, 50, 50);
10187
10188 // Move back to original window.
10189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010190 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungb89ccb02020-12-30 16:19:01 +080010191 ADISPLAY_ID_DEFAULT, {50, 50}))
10192 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010193 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010194 mWindow->consumeDragEvent(false, 50, 50);
10195 mSecondWindow->consumeDragEvent(true, -50, 50);
10196
10197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010198 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10199 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080010200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010201 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080010202 mWindow->assertNoEvents();
10203 mSecondWindow->assertNoEvents();
10204}
10205
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010206TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010207 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010208
10209 // No cancel event after drag start
10210 mSpyWindow->assertNoEvents();
10211
10212 const MotionEvent secondFingerDownEvent =
10213 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10214 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010215 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10216 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010217 .build();
10218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010219 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000010220 InputEventInjectionSync::WAIT_FOR_RESULT))
10221 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10222
10223 // Receives cancel for first pointer after next pointer down
10224 mSpyWindow->consumeMotionCancel();
10225 mSpyWindow->consumeMotionDown();
10226
10227 mSpyWindow->assertNoEvents();
10228}
10229
arthurhungf452d0b2021-01-06 00:19:52 +080010230TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010231 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080010232
10233 // Move on window.
10234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010235 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010236 ADISPLAY_ID_DEFAULT, {50, 50}))
10237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010238 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010239 mWindow->consumeDragEvent(false, 50, 50);
10240 mSecondWindow->assertNoEvents();
10241
10242 // Move to another window.
10243 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010244 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
arthurhungf452d0b2021-01-06 00:19:52 +080010245 ADISPLAY_ID_DEFAULT, {150, 50}))
10246 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010247 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080010248 mWindow->consumeDragEvent(true, 150, 50);
10249 mSecondWindow->consumeDragEvent(false, 50, 50);
10250
10251 // drop to another window.
10252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010253 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080010254 {150, 50}))
10255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010256 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010257 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080010258 mWindow->assertNoEvents();
10259 mSecondWindow->assertNoEvents();
10260}
10261
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010262TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
10263 startDrag();
10264
10265 // No cancel event after drag start
10266 mSpyWindow->assertNoEvents();
10267
10268 const MotionEvent secondFingerDownEvent =
10269 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10270 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10271 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10272 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10273 .build();
10274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10275 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10276 InputEventInjectionSync::WAIT_FOR_RESULT))
10277 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10278
10279 // Receives cancel for first pointer after next pointer down
10280 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080010281 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010282 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
10283
10284 mSpyWindow->assertNoEvents();
10285
10286 // Spy window calls pilfer pointers
10287 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
10288 mDragWindow->assertNoEvents();
10289
10290 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010291 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010292 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
10293 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
10294 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
10295 .build();
10296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080010297 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010298 InputEventInjectionSync::WAIT_FOR_RESULT))
10299 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10300
10301 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000010302 mDragWindow->consumeMotionEvent(
10303 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000010304 mDragWindow->assertNoEvents();
10305}
10306
arthurhung6d4bed92021-03-17 11:59:33 +080010307TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010308 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080010309
10310 // Move on window and keep button pressed.
10311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010312 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010313 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10314 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010315 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010316 .build()))
10317 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010318 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010319 mWindow->consumeDragEvent(false, 50, 50);
10320 mSecondWindow->assertNoEvents();
10321
10322 // Move to another window and release button, expect to drop item.
10323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010324 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010325 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
10326 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010327 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010328 .build()))
10329 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010330 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010331 mWindow->assertNoEvents();
10332 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010333 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080010334
10335 // nothing to the window.
10336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010337 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080010338 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
10339 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010340 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080010341 .build()))
10342 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010343 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080010344 mWindow->assertNoEvents();
10345 mSecondWindow->assertNoEvents();
10346}
10347
Arthur Hung54745652022-04-20 07:17:41 +000010348TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010349 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080010350
10351 // Set second window invisible.
10352 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010353 mDispatcher->onWindowInfosChanged(
10354 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080010355
10356 // Move on window.
10357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010358 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010359 ADISPLAY_ID_DEFAULT, {50, 50}))
10360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010361 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010362 mWindow->consumeDragEvent(false, 50, 50);
10363 mSecondWindow->assertNoEvents();
10364
10365 // Move to another window.
10366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010367 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010368 ADISPLAY_ID_DEFAULT, {150, 50}))
10369 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010370 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010371 mWindow->consumeDragEvent(true, 150, 50);
10372 mSecondWindow->assertNoEvents();
10373
10374 // drop to another window.
10375 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010376 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080010377 {150, 50}))
10378 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010379 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010380 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080010381 mWindow->assertNoEvents();
10382 mSecondWindow->assertNoEvents();
10383}
10384
Arthur Hung54745652022-04-20 07:17:41 +000010385TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010386 // Ensure window could track pointerIds if it didn't support split touch.
10387 mWindow->setPreventSplitting(true);
10388
Arthur Hung54745652022-04-20 07:17:41 +000010389 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010390 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010391 {50, 50}))
10392 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10393 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10394
10395 const MotionEvent secondFingerDownEvent =
10396 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10397 .displayId(ADISPLAY_ID_DEFAULT)
10398 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010399 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10400 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010401 .build();
10402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010403 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010404 InputEventInjectionSync::WAIT_FOR_RESULT))
10405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000010406 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000010407
10408 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010409 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010410}
10411
10412TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
10413 // First down on second window.
10414 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010415 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung54745652022-04-20 07:17:41 +000010416 {150, 50}))
10417 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10418
10419 mSecondWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10420
10421 // Second down on first window.
10422 const MotionEvent secondFingerDownEvent =
10423 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10424 .displayId(ADISPLAY_ID_DEFAULT)
10425 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010426 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10427 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010428 .build();
10429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010430 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010431 InputEventInjectionSync::WAIT_FOR_RESULT))
10432 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10433 mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +000010434 mSecondWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000010435
10436 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010437 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000010438
10439 // Move on window.
10440 const MotionEvent secondFingerMoveEvent =
10441 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10442 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010443 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10444 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010445 .build();
10446 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010447 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010448 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010449 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000010450 mWindow->consumeDragEvent(false, 50, 50);
10451 mSecondWindow->consumeMotionMove();
10452
10453 // Release the drag pointer should perform drop.
10454 const MotionEvent secondFingerUpEvent =
10455 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10456 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010457 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10458 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000010459 .build();
10460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010461 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000010462 InputEventInjectionSync::WAIT_FOR_RESULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +000010463 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010464 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000010465 mWindow->assertNoEvents();
10466 mSecondWindow->consumeMotionMove();
10467}
10468
Arthur Hung3915c1f2022-05-31 07:17:17 +000010469TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010470 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000010471
10472 // Update window of second display.
10473 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010474 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010475 mDispatcher->onWindowInfosChanged(
10476 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10477 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10478 {},
10479 0,
10480 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010481
10482 // Let second display has a touch state.
10483 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010484 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010485 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10486 AINPUT_SOURCE_TOUCHSCREEN)
10487 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010488 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000010489 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010490 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010491 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010492 mDispatcher->onWindowInfosChanged(
10493 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
10494 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
10495 {},
10496 0,
10497 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000010498
10499 // Move on window.
10500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010501 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010502 ADISPLAY_ID_DEFAULT, {50, 50}))
10503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010504 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010505 mWindow->consumeDragEvent(false, 50, 50);
10506 mSecondWindow->assertNoEvents();
10507
10508 // Move to another window.
10509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010510 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010511 ADISPLAY_ID_DEFAULT, {150, 50}))
10512 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010513 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000010514 mWindow->consumeDragEvent(true, 150, 50);
10515 mSecondWindow->consumeDragEvent(false, 50, 50);
10516
10517 // drop to another window.
10518 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010519 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000010520 {150, 50}))
10521 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010522 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010523 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000010524 mWindow->assertNoEvents();
10525 mSecondWindow->assertNoEvents();
10526}
10527
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010528TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
10529 startDrag(true, AINPUT_SOURCE_MOUSE);
10530 // Move on window.
10531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010532 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010533 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10534 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010535 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010536 .x(50)
10537 .y(50))
10538 .build()))
10539 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010540 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010541 mWindow->consumeDragEvent(false, 50, 50);
10542 mSecondWindow->assertNoEvents();
10543
10544 // Move to another window.
10545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010546 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010547 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
10548 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010549 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010550 .x(150)
10551 .y(50))
10552 .build()))
10553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010554 mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010555 mWindow->consumeDragEvent(true, 150, 50);
10556 mSecondWindow->consumeDragEvent(false, 50, 50);
10557
10558 // drop to another window.
10559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010560 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010561 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
10562 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010563 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010564 .x(150)
10565 .y(50))
10566 .build()))
10567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan65455c72024-02-13 21:46:41 +000010568 mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070010569 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000010570 mWindow->assertNoEvents();
10571 mSecondWindow->assertNoEvents();
10572}
10573
Linnan Li5af92f92023-07-14 14:36:22 +080010574/**
10575 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
10576 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
10577 */
10578TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
10579 // Down on second window
10580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10581 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10582 {150, 50}))
10583 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10584
10585 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
10586 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
10587
10588 // Down on first window
10589 const MotionEvent secondFingerDownEvent =
10590 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10591 .displayId(ADISPLAY_ID_DEFAULT)
10592 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
10593 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
10594 .build();
10595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10596 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
10597 InputEventInjectionSync::WAIT_FOR_RESULT))
10598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10599 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10600 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
10601 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
10602
10603 // Start drag on first window
10604 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
10605
10606 // Trigger cancel
10607 mDispatcher->cancelCurrentTouch();
10608 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Prabir Pradhan65455c72024-02-13 21:46:41 +000010609 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ADISPLAY_ID_DEFAULT,
10610 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080010611 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
10612
10613 ASSERT_TRUE(mDispatcher->waitForIdle());
10614 // The D&D finished with nullptr
10615 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
10616
10617 // Remove drag window
10618 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
10619
10620 // Inject a simple gesture, ensure dispatcher not crashed
10621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10622 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10623 PointF{50, 50}))
10624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10625 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10626
10627 const MotionEvent moveEvent =
10628 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10629 .displayId(ADISPLAY_ID_DEFAULT)
10630 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
10631 .build();
10632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10633 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
10634 InputEventInjectionSync::WAIT_FOR_RESULT))
10635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10636 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
10637
10638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10639 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
10640 {50, 50}))
10641 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10642 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
10643}
10644
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000010645TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
10646 // Start hovering over the window.
10647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10648 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
10649 ADISPLAY_ID_DEFAULT, {50, 50}));
10650
10651 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10652 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
10653
10654 ASSERT_FALSE(startDrag(/*sendDown=*/false))
10655 << "Drag and drop should not work with a hovering pointer";
10656}
10657
Vishnu Nair062a8672021-09-03 16:07:44 -070010658class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
10659
10660TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
10661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010662 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10663 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010664 window->setDropInput(true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010665 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10666 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010667 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010668 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010669 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010670
10671 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010672 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010673 window->assertNoEvents();
10674
Prabir Pradhan678438e2023-04-13 19:32:51 +000010675 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10676 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010677 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10678 ADISPLAY_ID_DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080010679 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070010680 window->assertNoEvents();
10681
10682 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010683 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010685
Prabir Pradhan678438e2023-04-13 19:32:51 +000010686 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010687 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10688
Prabir Pradhan678438e2023-04-13 19:32:51 +000010689 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10690 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010691 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10692 window->assertNoEvents();
10693}
10694
10695TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
10696 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10697 std::make_shared<FakeApplicationHandle>();
10698 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010699 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10700 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010701 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010702 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010703 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010705 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10706 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010707 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010708 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010709 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10710 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010711 mDispatcher->onWindowInfosChanged(
10712 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010713 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010714 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010715
10716 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010717 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010718 window->assertNoEvents();
10719
Prabir Pradhan678438e2023-04-13 19:32:51 +000010720 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10721 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010722 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10723 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010724 window->assertNoEvents();
10725
10726 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010727 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010728 mDispatcher->onWindowInfosChanged(
10729 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010730
Prabir Pradhan678438e2023-04-13 19:32:51 +000010731 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010732 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10733
Prabir Pradhan678438e2023-04-13 19:32:51 +000010734 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10735 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010736 window->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
10737 window->assertNoEvents();
10738}
10739
10740TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
10741 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
10742 std::make_shared<FakeApplicationHandle>();
10743 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010744 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
10745 ADISPLAY_ID_DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070010746 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010747 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010748 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070010749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010750 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
10751 "Test window", ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010752 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010753 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Vishnu Nair062a8672021-09-03 16:07:44 -070010754 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
10755 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010756 mDispatcher->onWindowInfosChanged(
10757 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010758 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000010759 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070010760
10761 // With the flag set, window should not get any input
Prabir Pradhan678438e2023-04-13 19:32:51 +000010762 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010763 window->assertNoEvents();
10764
Prabir Pradhan678438e2023-04-13 19:32:51 +000010765 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10766 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070010767 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
10768 ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010769 window->assertNoEvents();
10770
10771 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010772 mDispatcher->onWindowInfosChanged(
10773 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070010774
Prabir Pradhan678438e2023-04-13 19:32:51 +000010775 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010776 window->consumeKeyUp(ADISPLAY_ID_DEFAULT);
10777
Prabir Pradhan678438e2023-04-13 19:32:51 +000010778 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
10779 AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070010780 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10781 window->assertNoEvents();
10782}
10783
Antonio Kantekf16f2832021-09-28 04:39:20 +000010784class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
10785protected:
10786 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000010787 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010788 sp<FakeWindowHandle> mWindow;
10789 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000010790 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000010791
10792 void SetUp() override {
10793 InputDispatcherTest::SetUp();
10794
10795 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000010796 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010797 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010798 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010799 setFocusedWindow(mWindow);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010800 mSecondWindow =
10801 sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010802 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000010803 mThirdWindow =
10804 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
10805 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
10806 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010807
10808 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010809 mDispatcher->onWindowInfosChanged(
10810 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
10811 {},
10812 0,
10813 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000010814 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010815 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010816
Antonio Kantek15beb512022-06-13 22:35:41 +000010817 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000010818 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010819 WINDOW_UID, /*hasPermission=*/true, ADISPLAY_ID_DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070010820 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
10821 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010822 mThirdWindow->assertNoEvents();
10823 }
10824
10825 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
10826 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000010827 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000010828 SECOND_DISPLAY_ID)) {
10829 mWindow->assertNoEvents();
10830 mSecondWindow->assertNoEvents();
10831 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070010832 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000010833 }
10834
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010835 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000010836 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070010837 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
10838 ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010839 mWindow->consumeTouchModeEvent(inTouchMode);
10840 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000010841 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000010842 }
10843};
10844
Antonio Kantek26defcf2022-02-08 01:12:27 +000010845TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010846 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000010847 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
10848 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010849 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000010850}
10851
Antonio Kantek26defcf2022-02-08 01:12:27 +000010852TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
10853 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010854 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010855 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010856 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010857 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010858 ownerUid, /*hasPermission=*/false,
Antonio Kanteka042c022022-07-06 16:51:07 -070010859 ADISPLAY_ID_DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000010860 mWindow->assertNoEvents();
10861 mSecondWindow->assertNoEvents();
10862}
10863
10864TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
10865 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010866 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000010867 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000010868 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000010869 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000010870 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000010871}
10872
Antonio Kantekf16f2832021-09-28 04:39:20 +000010873TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080010874 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000010875 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
10876 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010877 /*hasPermission=*/true, ADISPLAY_ID_DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000010878 mWindow->assertNoEvents();
10879 mSecondWindow->assertNoEvents();
10880}
10881
Antonio Kantek15beb512022-06-13 22:35:41 +000010882TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
10883 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
10884 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10885 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010886 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000010887 mWindow->assertNoEvents();
10888 mSecondWindow->assertNoEvents();
10889 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
10890}
10891
Antonio Kantek48710e42022-03-24 14:19:30 -070010892TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
10893 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10895 injectKeyDown(*mDispatcher, ADISPLAY_ID_DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070010896 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
10897 mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
10898
10899 // Then remove focus.
10900 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010901 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070010902
10903 // Assert that caller can switch touch mode by owning one of the last interacted window.
10904 const WindowInfo& windowInfo = *mWindow->getInfo();
10905 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
10906 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000010907 /*hasPermission=*/false, ADISPLAY_ID_DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070010908}
10909
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010910class InputDispatcherSpyWindowTest : public InputDispatcherTest {
10911public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010912 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010913 std::shared_ptr<FakeApplicationHandle> application =
10914 std::make_shared<FakeApplicationHandle>();
10915 std::string name = "Fake Spy ";
10916 name += std::to_string(mSpyCount++);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010917 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher,
10918 name.c_str(), ADISPLAY_ID_DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010919 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010920 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010921 return spy;
10922 }
10923
10924 sp<FakeWindowHandle> createForeground() {
10925 std::shared_ptr<FakeApplicationHandle> application =
10926 std::make_shared<FakeApplicationHandle>();
10927 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010928 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
10929 ADISPLAY_ID_DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010930 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010931 return window;
10932 }
10933
10934private:
10935 int mSpyCount{0};
10936};
10937
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010938using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010939/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010940 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
10941 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010942TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070010943 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080010944 ScopedSilentDeath _silentDeath;
10945
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010946 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010947 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010948 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080010949 ".* not a trusted overlay");
10950}
10951
10952/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010953 * Input injection into a display with a spy window but no foreground windows should succeed.
10954 */
10955TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010956 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010957 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010958
10959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010960 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010961 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
10962 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
10963}
10964
10965/**
10966 * Verify the order in which different input windows receive events. The touched foreground window
10967 * (if there is one) should always receive the event first. When there are multiple spy windows, the
10968 * spy windows will receive the event according to their Z-order, where the top-most spy window will
10969 * receive events before ones belows it.
10970 *
10971 * Here, we set up a scenario with four windows in the following Z order from the top:
10972 * spy1, spy2, window, spy3.
10973 * We then inject an event and verify that the foreground "window" receives it first, followed by
10974 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
10975 * window.
10976 */
10977TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
10978 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010979 auto spy1 = createSpy();
10980 auto spy2 = createSpy();
10981 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010982 mDispatcher->onWindowInfosChanged(
10983 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010984 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
10985 const size_t numChannels = channels.size();
10986
Michael Wright8e9a8562022-02-09 13:44:29 +000010987 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080010988 if (!epollFd.ok()) {
10989 FAIL() << "Failed to create epoll fd";
10990 }
10991
10992 for (size_t i = 0; i < numChannels; i++) {
10993 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
10994 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
10995 FAIL() << "Failed to add fd to epoll";
10996 }
10997 }
10998
10999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011000 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011001 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11002
11003 std::vector<size_t> eventOrder;
11004 std::vector<struct epoll_event> events(numChannels);
11005 for (;;) {
11006 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
11007 (100ms).count());
11008 if (nFds < 0) {
11009 FAIL() << "Failed to call epoll_wait";
11010 }
11011 if (nFds == 0) {
11012 break; // epoll_wait timed out
11013 }
11014 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070011015 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070011016 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011017 channels[i]->consumeMotionDown();
11018 }
11019 }
11020
11021 // Verify the order in which the events were received.
11022 EXPECT_EQ(3u, eventOrder.size());
11023 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
11024 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
11025 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
11026}
11027
11028/**
11029 * A spy window using the NOT_TOUCHABLE flag does not receive events.
11030 */
11031TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
11032 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011033 auto spy = createSpy();
11034 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011035 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011036
11037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011039 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11040 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11041 spy->assertNoEvents();
11042}
11043
11044/**
11045 * A spy window will only receive gestures that originate within its touchable region. Gestures that
11046 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
11047 * to the window.
11048 */
11049TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
11050 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011051 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011052 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011053 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011054
11055 // Inject an event outside the spy window's touchable region.
11056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011057 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011058 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11059 window->consumeMotionDown();
11060 spy->assertNoEvents();
11061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011062 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11064 window->consumeMotionUp();
11065 spy->assertNoEvents();
11066
11067 // Inject an event inside the spy window's touchable region.
11068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011069 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011070 {5, 10}))
11071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11072 window->consumeMotionDown();
11073 spy->consumeMotionDown();
11074}
11075
11076/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011077 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011078 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011079 */
11080TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
11081 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011082 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011083 auto spy = createSpy();
11084 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011085 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011086 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011087 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011088
11089 // Inject an event outside the spy window's frame and touchable region.
11090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011091 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011092 {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011093 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11094 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011095 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011096}
11097
11098/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011099 * Even when a spy window spans over multiple foreground windows, the spy should receive all
11100 * pointers that are down within its bounds.
11101 */
11102TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
11103 auto windowLeft = createForeground();
11104 windowLeft->setFrame({0, 0, 100, 200});
11105 auto windowRight = createForeground();
11106 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011107 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011108 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011109 mDispatcher->onWindowInfosChanged(
11110 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011111
11112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011113 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011114 {50, 50}))
11115 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11116 windowLeft->consumeMotionDown();
11117 spy->consumeMotionDown();
11118
11119 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011120 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011121 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011122 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11123 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011124 .build();
11125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011126 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011127 InputEventInjectionSync::WAIT_FOR_RESULT))
11128 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11129 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000011130 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011131}
11132
11133/**
11134 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
11135 * the spy should receive the second pointer with ACTION_DOWN.
11136 */
11137TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
11138 auto window = createForeground();
11139 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011140 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011141 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011142 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011143
11144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011145 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011146 {50, 50}))
11147 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11148 window->consumeMotionDown();
11149 spyRight->assertNoEvents();
11150
11151 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011152 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011153 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011154 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11155 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011156 .build();
11157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011158 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011159 InputEventInjectionSync::WAIT_FOR_RESULT))
11160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011161 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080011162 spyRight->consumeMotionDown();
11163}
11164
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011165/**
11166 * The spy window should not be able to affect whether or not touches are split. Only the foreground
11167 * windows should be allowed to control split touch.
11168 */
11169TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011170 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011171 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011172 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080011173 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011174
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011175 auto window = createForeground();
11176 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011177
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011178 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011179
11180 // First finger down, no window touched.
11181 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011182 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011183 {100, 200}))
11184 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11185 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11186 window->assertNoEvents();
11187
11188 // Second finger down on window, the window should receive touch down.
11189 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080011190 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011191 .displayId(ADISPLAY_ID_DEFAULT)
11192 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011193 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11194 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011195 .build();
11196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011197 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011198 InputEventInjectionSync::WAIT_FOR_RESULT))
11199 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11200
11201 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000011202 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011203}
11204
11205/**
11206 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
11207 * do not receive key events.
11208 */
11209TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011210 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011211 spy->setFocusable(false);
11212
11213 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011214 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011215 setFocusedWindow(window);
11216 window->consumeFocusEvent(true);
11217
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011218 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011219 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11220 window->consumeKeyDown(ADISPLAY_ID_NONE);
11221
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080011223 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
11224 window->consumeKeyUp(ADISPLAY_ID_NONE);
11225
11226 spy->assertNoEvents();
11227}
11228
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011229using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
11230
11231/**
11232 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
11233 * are currently sent to any other windows - including other spy windows - will also be cancelled.
11234 */
11235TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
11236 auto window = createForeground();
11237 auto spy1 = createSpy();
11238 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011239 mDispatcher->onWindowInfosChanged(
11240 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011241
11242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011244 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11245 window->consumeMotionDown();
11246 spy1->consumeMotionDown();
11247 spy2->consumeMotionDown();
11248
11249 // Pilfer pointers from the second spy window.
11250 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
11251 spy2->assertNoEvents();
11252 spy1->consumeMotionCancel();
11253 window->consumeMotionCancel();
11254
11255 // The rest of the gesture should only be sent to the second spy window.
11256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011257 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011258 ADISPLAY_ID_DEFAULT))
11259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11260 spy2->consumeMotionMove();
11261 spy1->assertNoEvents();
11262 window->assertNoEvents();
11263}
11264
11265/**
11266 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
11267 * in the middle of the gesture.
11268 */
11269TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
11270 auto window = createForeground();
11271 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011272 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011273
11274 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011275 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11277 window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11278 spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
11279
11280 window->releaseChannel();
11281
11282 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11283
11284 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011285 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011286 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11287 spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
11288}
11289
11290/**
11291 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
11292 * the spy, but not to any other windows.
11293 */
11294TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
11295 auto spy = createSpy();
11296 auto window = createForeground();
11297
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011298 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011299
11300 // First finger down on the window and the spy.
11301 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011302 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011303 {100, 200}))
11304 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11305 spy->consumeMotionDown();
11306 window->consumeMotionDown();
11307
11308 // Spy window pilfers the pointers.
11309 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11310 window->consumeMotionCancel();
11311
11312 // Second finger down on the window and spy, but the window should not receive the pointer down.
11313 const MotionEvent secondFingerDownEvent =
11314 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11315 .displayId(ADISPLAY_ID_DEFAULT)
11316 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011317 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11318 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011319 .build();
11320 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011321 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011322 InputEventInjectionSync::WAIT_FOR_RESULT))
11323 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11324
Harry Cutts33476232023-01-30 19:57:29 +000011325 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011326
11327 // Third finger goes down outside all windows, so injection should fail.
11328 const MotionEvent thirdFingerDownEvent =
11329 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11330 .displayId(ADISPLAY_ID_DEFAULT)
11331 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011332 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
11333 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
11334 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011335 .build();
11336 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011337 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011338 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080011339 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011340
11341 spy->assertNoEvents();
11342 window->assertNoEvents();
11343}
11344
11345/**
11346 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
11347 */
11348TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
11349 auto spy = createSpy();
11350 spy->setFrame(Rect(0, 0, 100, 100));
11351 auto window = createForeground();
11352 window->setFrame(Rect(0, 0, 200, 200));
11353
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011354 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011355
11356 // First finger down on the window only
11357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011358 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011359 {150, 150}))
11360 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11361 window->consumeMotionDown();
11362
11363 // Second finger down on the spy and window
11364 const MotionEvent secondFingerDownEvent =
11365 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11366 .displayId(ADISPLAY_ID_DEFAULT)
11367 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011368 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11369 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011370 .build();
11371 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011372 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011373 InputEventInjectionSync::WAIT_FOR_RESULT))
11374 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11375 spy->consumeMotionDown();
11376 window->consumeMotionPointerDown(1);
11377
11378 // Third finger down on the spy and window
11379 const MotionEvent thirdFingerDownEvent =
11380 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11381 .displayId(ADISPLAY_ID_DEFAULT)
11382 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011383 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
11384 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
11385 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011386 .build();
11387 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011388 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011389 InputEventInjectionSync::WAIT_FOR_RESULT))
11390 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11391 spy->consumeMotionPointerDown(1);
11392 window->consumeMotionPointerDown(2);
11393
11394 // Spy window pilfers the pointers.
11395 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Harry Cutts101ee9b2023-07-06 18:04:14 +000011396 window->consumeMotionPointerUp(/*idx=*/2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
11397 window->consumeMotionPointerUp(/*idx=*/1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011398
11399 spy->assertNoEvents();
11400 window->assertNoEvents();
11401}
11402
11403/**
11404 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
11405 * other windows should be canceled. If this results in the cancellation of all pointers for some
11406 * window, then that window should receive ACTION_CANCEL.
11407 */
11408TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
11409 auto spy = createSpy();
11410 spy->setFrame(Rect(0, 0, 100, 100));
11411 auto window = createForeground();
11412 window->setFrame(Rect(0, 0, 200, 200));
11413
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011414 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011415
11416 // First finger down on both spy and window
11417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011418 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011419 {10, 10}))
11420 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11421 window->consumeMotionDown();
11422 spy->consumeMotionDown();
11423
11424 // Second finger down on the spy and window
11425 const MotionEvent secondFingerDownEvent =
11426 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11427 .displayId(ADISPLAY_ID_DEFAULT)
11428 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011429 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11430 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011431 .build();
11432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011433 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011434 InputEventInjectionSync::WAIT_FOR_RESULT))
11435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11436 spy->consumeMotionPointerDown(1);
11437 window->consumeMotionPointerDown(1);
11438
11439 // Spy window pilfers the pointers.
11440 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11441 window->consumeMotionCancel();
11442
11443 spy->assertNoEvents();
11444 window->assertNoEvents();
11445}
11446
11447/**
11448 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
11449 * be sent to other windows
11450 */
11451TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
11452 auto spy = createSpy();
11453 spy->setFrame(Rect(0, 0, 100, 100));
11454 auto window = createForeground();
11455 window->setFrame(Rect(0, 0, 200, 200));
11456
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011457 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011458
11459 // First finger down on both window and spy
11460 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011461 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011462 {10, 10}))
11463 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11464 window->consumeMotionDown();
11465 spy->consumeMotionDown();
11466
11467 // Spy window pilfers the pointers.
11468 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
11469 window->consumeMotionCancel();
11470
11471 // Second finger down on the window only
11472 const MotionEvent secondFingerDownEvent =
11473 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11474 .displayId(ADISPLAY_ID_DEFAULT)
11475 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011476 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
11477 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011478 .build();
11479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011480 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000011481 InputEventInjectionSync::WAIT_FOR_RESULT))
11482 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11483 window->consumeMotionDown();
11484 window->assertNoEvents();
11485
11486 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
11487 spy->consumeMotionMove();
11488 spy->assertNoEvents();
11489}
11490
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011491/**
11492 * A window on the left and a window on the right. Also, a spy window that's above all of the
11493 * windows, and spanning both left and right windows.
11494 * Send simultaneous motion streams from two different devices, one to the left window, and another
11495 * to the right window.
11496 * Pilfer from spy window.
11497 * Check that the pilfering only affects the pointers that are actually being received by the spy.
11498 */
11499TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
11500 sp<FakeWindowHandle> spy = createSpy();
11501 spy->setFrame(Rect(0, 0, 200, 200));
11502 sp<FakeWindowHandle> leftWindow = createForeground();
11503 leftWindow->setFrame(Rect(0, 0, 100, 100));
11504
11505 sp<FakeWindowHandle> rightWindow = createForeground();
11506 rightWindow->setFrame(Rect(100, 0, 200, 100));
11507
11508 constexpr int32_t stylusDeviceId = 1;
11509 constexpr int32_t touchDeviceId = 2;
11510
11511 mDispatcher->onWindowInfosChanged(
11512 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
11513
11514 // Stylus down on left window and spy
11515 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
11516 .deviceId(stylusDeviceId)
11517 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
11518 .build());
11519 leftWindow->consumeMotionEvent(
11520 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11521 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
11522
11523 // Finger down on right window and spy - but spy already has stylus
11524 mDispatcher->notifyMotion(
11525 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11526 .deviceId(touchDeviceId)
11527 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
11528 .build());
11529 rightWindow->consumeMotionEvent(
11530 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011531 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011532
11533 // Act: pilfer from spy. Spy is currently receiving touch events.
11534 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011535 leftWindow->consumeMotionEvent(
11536 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011537 rightWindow->consumeMotionEvent(
11538 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
11539
11540 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
11541 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11542 .deviceId(stylusDeviceId)
11543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
11544 .build());
11545 mDispatcher->notifyMotion(
11546 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11547 .deviceId(touchDeviceId)
11548 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
11549 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070011550 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011551
11552 spy->assertNoEvents();
11553 leftWindow->assertNoEvents();
11554 rightWindow->assertNoEvents();
11555}
11556
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000011557TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
11558 auto window = createForeground();
11559 auto spy = createSpy();
11560 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
11561
11562 mDispatcher->notifyMotion(
11563 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11564 .deviceId(1)
11565 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
11566 .build());
11567 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11568 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11569
11570 // Pilfer pointers from the spy window should fail.
11571 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
11572 spy->assertNoEvents();
11573 window->assertNoEvents();
11574}
11575
Prabir Pradhand65552b2021-10-07 11:23:50 -070011576class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
11577public:
11578 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
11579 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11580 std::make_shared<FakeApplicationHandle>();
11581 sp<FakeWindowHandle> overlay =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011582 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11583 "Stylus interceptor window", ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011584 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011585 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011586 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011587 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011588 overlay->setTrustedOverlay(true);
11589
11590 std::shared_ptr<FakeApplicationHandle> application =
11591 std::make_shared<FakeApplicationHandle>();
11592 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011593 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
11594 ADISPLAY_ID_DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011595 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011596 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011597
11598 mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011599 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011600 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000011601 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011602 return {std::move(overlay), std::move(window)};
11603 }
11604
11605 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011606 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070011607 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011608 ADISPLAY_ID_DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070011609 }
11610
11611 void sendStylusEvent(int32_t action) {
11612 NotifyMotionArgs motionArgs =
11613 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
11614 ADISPLAY_ID_DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011615 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000011616 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070011617 }
11618};
11619
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011620using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
11621
11622TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070011623 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080011624 ScopedSilentDeath _silentDeath;
11625
Prabir Pradhand65552b2021-10-07 11:23:50 -070011626 auto [overlay, window] = setupStylusOverlayScenario();
11627 overlay->setTrustedOverlay(false);
11628 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011629 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
11630 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070011631 ".* not a trusted overlay");
11632}
11633
11634TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
11635 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011636 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011637
11638 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11639 overlay->consumeMotionDown();
11640 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11641 overlay->consumeMotionUp();
11642
11643 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11644 window->consumeMotionDown();
11645 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11646 window->consumeMotionUp();
11647
11648 overlay->assertNoEvents();
11649 window->assertNoEvents();
11650}
11651
11652TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
11653 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011654 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011655 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070011656
11657 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11658 overlay->consumeMotionDown();
11659 window->consumeMotionDown();
11660 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11661 overlay->consumeMotionUp();
11662 window->consumeMotionUp();
11663
11664 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
11665 window->consumeMotionDown();
11666 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
11667 window->consumeMotionUp();
11668
11669 overlay->assertNoEvents();
11670 window->assertNoEvents();
11671}
11672
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011673/**
11674 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
11675 * The scenario is as follows:
11676 * - The stylus interceptor overlay is configured as a spy window.
11677 * - The stylus interceptor spy receives the start of a new stylus gesture.
11678 * - It pilfers pointers and then configures itself to no longer be a spy.
11679 * - The stylus interceptor continues to receive the rest of the gesture.
11680 */
11681TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
11682 auto [overlay, window] = setupStylusOverlayScenario();
11683 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011684 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011685
11686 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
11687 overlay->consumeMotionDown();
11688 window->consumeMotionDown();
11689
11690 // The interceptor pilfers the pointers.
11691 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
11692 window->consumeMotionCancel();
11693
11694 // The interceptor configures itself so that it is no longer a spy.
11695 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011696 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000011697
11698 // It continues to receive the rest of the stylus gesture.
11699 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
11700 overlay->consumeMotionMove();
11701 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
11702 overlay->consumeMotionUp();
11703
11704 window->assertNoEvents();
11705}
11706
Prabir Pradhan5735a322022-04-11 17:23:34 +000011707struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011708 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011709 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000011710 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
11711 std::unique_ptr<InputDispatcher>& mDispatcher;
11712
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011713 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000011714 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
11715
11716 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011717 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011718 ADISPLAY_ID_DEFAULT, {100, 200},
11719 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
11720 AMOTION_EVENT_INVALID_CURSOR_POSITION},
11721 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
11722 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
11723 }
11724
11725 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011726 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0, ADISPLAY_ID_NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011727 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000011728 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000011729 mPolicyFlags);
11730 }
11731
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011732 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000011733 std::shared_ptr<FakeApplicationHandle> overlayApplication =
11734 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011735 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
11736 name, ADISPLAY_ID_DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000011737 window->setOwnerInfo(mPid, mUid);
11738 return window;
11739 }
11740};
11741
11742using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
11743
11744TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011745 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011746 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011747 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011748
11749 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11750 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11751 window->consumeMotionDown();
11752
11753 setFocusedWindow(window);
11754 window->consumeFocusEvent(true);
11755
11756 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11757 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11758 window->consumeKeyDown(ADISPLAY_ID_NONE);
11759}
11760
11761TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011762 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011763 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011764 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011765
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011766 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011767 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11768 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11769
11770 setFocusedWindow(window);
11771 window->consumeFocusEvent(true);
11772
11773 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
11774 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
11775 window->assertNoEvents();
11776}
11777
11778TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011779 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011780 auto window = owner.createWindow("Owned window");
11781 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011782 spy->setSpy(true);
11783 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011784 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011785
11786 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11787 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11788 spy->consumeMotionDown();
11789 window->consumeMotionDown();
11790}
11791
11792TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011793 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011794 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011795
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011796 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011797 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011798 randosSpy->setSpy(true);
11799 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011800 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011801
11802 // The event is targeted at owner's window, so injection should succeed, but the spy should
11803 // not receive the event.
11804 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11805 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11806 randosSpy->assertNoEvents();
11807 window->consumeMotionDown();
11808}
11809
11810TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011811 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011812 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011813
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011814 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011815 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011816 randosSpy->setSpy(true);
11817 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011818 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011819
11820 // A user that has injection permission can inject into any window.
11821 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011822 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Prabir Pradhan5735a322022-04-11 17:23:34 +000011823 ADISPLAY_ID_DEFAULT));
11824 randosSpy->consumeMotionDown();
11825 window->consumeMotionDown();
11826
11827 setFocusedWindow(randosSpy);
11828 randosSpy->consumeFocusEvent(true);
11829
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011830 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Prabir Pradhan5735a322022-04-11 17:23:34 +000011831 randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
11832 window->assertNoEvents();
11833}
11834
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011835TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011836 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011837 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011838
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011839 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070011840 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000011841 randosWindow->setFrame(Rect{-10, -10, -5, -5});
11842 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011843 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000011844
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011845 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000011846 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
11847 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
11848 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070011849 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000011850}
11851
Prabir Pradhan64f21d22023-11-28 21:19:42 +000011852using InputDispatcherPointerInWindowTest = InputDispatcherTest;
11853
11854TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
11855 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11856
11857 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11858 ADISPLAY_ID_DEFAULT);
11859 left->setFrame(Rect(0, 0, 100, 100));
11860 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11861 "Right Window", ADISPLAY_ID_DEFAULT);
11862 right->setFrame(Rect(100, 0, 200, 100));
11863 sp<FakeWindowHandle> spy =
11864 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11865 spy->setFrame(Rect(0, 0, 200, 100));
11866 spy->setTrustedOverlay(true);
11867 spy->setSpy(true);
11868
11869 mDispatcher->onWindowInfosChanged(
11870 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11871
11872 // Hover into the left window.
11873 mDispatcher->notifyMotion(
11874 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
11875 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
11876 .build());
11877
11878 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11879 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11880
11881 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11882 /*pointerId=*/0));
11883 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11884 /*pointerId=*/0));
11885 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11886 /*pointerId=*/0));
11887
11888 // Hover move to the right window.
11889 mDispatcher->notifyMotion(
11890 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
11891 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11892 .build());
11893
11894 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11895 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
11896 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
11897
11898 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11899 /*pointerId=*/0));
11900 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11901 /*pointerId=*/0));
11902 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11903 /*pointerId=*/0));
11904
11905 // Stop hovering.
11906 mDispatcher->notifyMotion(
11907 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
11908 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
11909 .build());
11910
11911 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11912 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
11913
11914 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11915 /*pointerId=*/0));
11916 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11917 /*pointerId=*/0));
11918 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11919 /*pointerId=*/0));
11920}
11921
11922TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
11923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
11924
11925 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
11926 ADISPLAY_ID_DEFAULT);
11927 left->setFrame(Rect(0, 0, 100, 100));
11928 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
11929 "Right Window", ADISPLAY_ID_DEFAULT);
11930 right->setFrame(Rect(100, 0, 200, 100));
11931 sp<FakeWindowHandle> spy =
11932 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
11933 spy->setFrame(Rect(0, 0, 200, 100));
11934 spy->setTrustedOverlay(true);
11935 spy->setSpy(true);
11936
11937 mDispatcher->onWindowInfosChanged(
11938 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
11939
11940 // First pointer down on left window.
11941 mDispatcher->notifyMotion(
11942 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11943 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11944 .build());
11945
11946 left->consumeMotionDown();
11947 spy->consumeMotionDown();
11948
11949 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11950 /*pointerId=*/0));
11951 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11952 /*pointerId=*/0));
11953 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11954 /*pointerId=*/0));
11955
11956 // Second pointer down on right window.
11957 mDispatcher->notifyMotion(
11958 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11959 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11960 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11961 .build());
11962
11963 left->consumeMotionMove();
11964 right->consumeMotionDown();
11965 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
11966
11967 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11968 /*pointerId=*/0));
11969 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11970 /*pointerId=*/0));
11971 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11972 /*pointerId=*/0));
11973 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11974 /*pointerId=*/1));
11975 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11976 /*pointerId=*/1));
11977 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11978 /*pointerId=*/1));
11979
11980 // Second pointer up.
11981 mDispatcher->notifyMotion(
11982 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11983 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11984 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
11985 .build());
11986
11987 left->consumeMotionMove();
11988 right->consumeMotionUp();
11989 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
11990
11991 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11992 /*pointerId=*/0));
11993 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11994 /*pointerId=*/0));
11995 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11996 /*pointerId=*/0));
11997 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
11998 /*pointerId=*/1));
11999 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12000 /*pointerId=*/1));
12001 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12002 /*pointerId=*/1));
12003
12004 // First pointer up.
12005 mDispatcher->notifyMotion(
12006 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12007 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12008 .build());
12009
12010 left->consumeMotionUp();
12011 spy->consumeMotionUp();
12012
12013 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12014 /*pointerId=*/0));
12015 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12016 /*pointerId=*/0));
12017 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12018 /*pointerId=*/0));
12019}
12020
12021TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
12022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
12023
12024 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
12025 ADISPLAY_ID_DEFAULT);
12026 left->setFrame(Rect(0, 0, 100, 100));
12027 sp<FakeWindowHandle> right = sp<FakeWindowHandle>::make(application, mDispatcher,
12028 "Right Window", ADISPLAY_ID_DEFAULT);
12029 right->setFrame(Rect(100, 0, 200, 100));
12030
12031 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
12032
12033 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12034 /*pointerId=*/0));
12035 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12036 /*pointerId=*/0));
12037
12038 // Hover move into the window.
12039 mDispatcher->notifyMotion(
12040 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12041 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
12042 .rawXCursorPosition(50)
12043 .rawYCursorPosition(50)
12044 .deviceId(DEVICE_ID)
12045 .build());
12046
12047 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12048
12049 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12050 /*pointerId=*/0));
12051
12052 // Move the mouse with another device. This cancels the hovering pointer from the first device.
12053 mDispatcher->notifyMotion(
12054 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12055 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
12056 .rawXCursorPosition(51)
12057 .rawYCursorPosition(50)
12058 .deviceId(SECOND_DEVICE_ID)
12059 .build());
12060
12061 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12062 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12063
12064 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
12065 // a HOVER_EXIT from the first device.
12066 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12067 /*pointerId=*/0));
12068 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12069 SECOND_DEVICE_ID,
12070 /*pointerId=*/0));
12071
12072 // Move the mouse outside the window. Document the current behavior, where the window does not
12073 // receive HOVER_EXIT even though the mouse left the window.
12074 mDispatcher->notifyMotion(
12075 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
12076 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
12077 .rawXCursorPosition(150)
12078 .rawYCursorPosition(50)
12079 .deviceId(SECOND_DEVICE_ID)
12080 .build());
12081
12082 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
12083 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
12084 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT, DEVICE_ID,
12085 /*pointerId=*/0));
12086 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ADISPLAY_ID_DEFAULT,
12087 SECOND_DEVICE_ID,
12088 /*pointerId=*/0));
12089}
12090
Garfield Tane84e6f92019-08-29 17:28:41 -070012091} // namespace android::inputdispatcher