blob: 46e7e8b35e1890fe2d1d9629717aa0ee7eb23ae4 [file] [log] [blame]
Garfield Tane84e6f92019-08-29 17:28:41 -07001/*
2 * Copyright (C) 2019 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
Arthur Hung1a1007b2022-05-11 07:15:01 +000017#include "DebugConfig.h"
Chris Yef59a2f42020-10-16 12:55:26 -070018#include "input/InputDevice.h"
19
Garfield Tane84e6f92019-08-29 17:28:41 -070020#include "InputState.h"
21
Arthur Hung1a1007b2022-05-11 07:15:01 +000022#include <cinttypes>
Garfield Tanff1f1bb2020-01-28 13:24:04 -080023#include "InputDispatcher.h"
24
Garfield Tane84e6f92019-08-29 17:28:41 -070025namespace android::inputdispatcher {
26
Garfield Tanff1f1bb2020-01-28 13:24:04 -080027InputState::InputState(const IdGenerator& idGenerator) : mIdGenerator(idGenerator) {}
Garfield Tane84e6f92019-08-29 17:28:41 -070028
29InputState::~InputState() {}
30
Linnan Li13bf76a2024-05-05 19:18:02 +080031bool InputState::isHovering(DeviceId deviceId, uint32_t source,
32 ui::LogicalDisplayId displayId) const {
Garfield Tane84e6f92019-08-29 17:28:41 -070033 for (const MotionMemento& memento : mMotionMementos) {
34 if (memento.deviceId == deviceId && memento.source == source &&
35 memento.displayId == displayId && memento.hovering) {
36 return true;
37 }
38 }
39 return false;
40}
41
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +000042bool InputState::trackKey(const KeyEntry& entry, int32_t flags) {
43 switch (entry.action) {
Garfield Tane84e6f92019-08-29 17:28:41 -070044 case AKEY_EVENT_ACTION_UP: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070045 if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -070046 std::erase_if(mFallbackKeys,
47 [&entry](const auto& item) { return item.second == entry.keyCode; });
Garfield Tane84e6f92019-08-29 17:28:41 -070048 }
49 ssize_t index = findKeyMemento(entry);
50 if (index >= 0) {
51 mKeyMementos.erase(mKeyMementos.begin() + index);
52 return true;
53 }
54 /* FIXME: We can't just drop the key up event because that prevents creating
55 * popup windows that are automatically shown when a key is held and then
56 * dismissed when the key is released. The problem is that the popup will
57 * not have received the original key down, so the key up will be considered
58 * to be inconsistent with its observed state. We could perhaps handle this
59 * by synthesizing a key down but that will cause other problems.
60 *
61 * So for now, allow inconsistent key up events to be dispatched.
62 *
63 #if DEBUG_OUTBOUND_EVENT_DETAILS
64 ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
65 "keyCode=%d, scanCode=%d",
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070066 entry.deviceId, entry.source, entry.keyCode, entry.scanCode);
Garfield Tane84e6f92019-08-29 17:28:41 -070067 #endif
68 return false;
69 */
70 return true;
71 }
72
73 case AKEY_EVENT_ACTION_DOWN: {
74 ssize_t index = findKeyMemento(entry);
75 if (index >= 0) {
76 mKeyMementos.erase(mKeyMementos.begin() + index);
77 }
78 addKeyMemento(entry, flags);
79 return true;
80 }
81
82 default:
83 return true;
84 }
85}
86
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070087/**
88 * Return:
89 * true if the incoming event was correctly tracked,
90 * false if the incoming event should be dropped.
91 */
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +000092bool InputState::trackMotion(const MotionEntry& entry, int32_t flags) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070093 // Don't track non-pointer events
94 if (!isFromSource(entry.source, AINPUT_SOURCE_CLASS_POINTER)) {
95 // This is a focus-dispatched event; we don't track its state.
96 return true;
97 }
98
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070099 if (!input_flags::enable_multi_device_same_window_stream()) {
100 if (!mMotionMementos.empty()) {
101 const MotionMemento& lastMemento = mMotionMementos.back();
102 if (isStylusEvent(lastMemento.source, lastMemento.pointerProperties) &&
103 !isStylusEvent(entry.source, entry.pointerProperties)) {
104 // We already have a stylus stream, and the new event is not from stylus.
105 return false;
106 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700107 }
108 }
109
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000110 int32_t actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
Garfield Tane84e6f92019-08-29 17:28:41 -0700111 switch (actionMasked) {
112 case AMOTION_EVENT_ACTION_UP:
113 case AMOTION_EVENT_ACTION_CANCEL: {
Harry Cutts33476232023-01-30 19:57:29 +0000114 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700115 if (index >= 0) {
116 mMotionMementos.erase(mMotionMementos.begin() + index);
117 return true;
118 }
Siarhei Vishniakouc94dafe2023-05-26 10:24:19 -0700119
Garfield Tane84e6f92019-08-29 17:28:41 -0700120 return false;
121 }
122
123 case AMOTION_EVENT_ACTION_DOWN: {
Harry Cutts33476232023-01-30 19:57:29 +0000124 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700125 if (index >= 0) {
126 mMotionMementos.erase(mMotionMementos.begin() + index);
127 }
Harry Cutts33476232023-01-30 19:57:29 +0000128 addMotionMemento(entry, flags, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700129 return true;
130 }
131
132 case AMOTION_EVENT_ACTION_POINTER_UP:
133 case AMOTION_EVENT_ACTION_POINTER_DOWN:
134 case AMOTION_EVENT_ACTION_MOVE: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700135 if (entry.source & AINPUT_SOURCE_CLASS_NAVIGATION) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700136 // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need
137 // to generate cancellation events for these since they're based in relative rather
138 // than absolute units.
139 return true;
140 }
141
Harry Cutts33476232023-01-30 19:57:29 +0000142 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700143
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700144 if (entry.source & AINPUT_SOURCE_CLASS_JOYSTICK) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700145 // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
146 // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral.
147 // Any other value and we need to track the motion so we can send cancellation
148 // events for anything generating fallback events (e.g. DPad keys for joystick
149 // movements).
150 if (index >= 0) {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700151 if (entry.pointerCoords[0].isEmpty()) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700152 mMotionMementos.erase(mMotionMementos.begin() + index);
153 } else {
154 MotionMemento& memento = mMotionMementos[index];
155 memento.setPointers(entry);
156 }
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700157 } else if (!entry.pointerCoords[0].isEmpty()) {
Harry Cutts33476232023-01-30 19:57:29 +0000158 addMotionMemento(entry, flags, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700159 }
160
161 // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
162 return true;
163 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800164
Garfield Tane84e6f92019-08-29 17:28:41 -0700165 if (index >= 0) {
166 MotionMemento& memento = mMotionMementos[index];
Svet Ganov5d3bc372020-01-26 23:11:07 -0800167 if (memento.firstNewPointerIdx < 0) {
168 memento.setPointers(entry);
169 return true;
170 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700171 }
Siarhei Vishniakouc94dafe2023-05-26 10:24:19 -0700172
Garfield Tane84e6f92019-08-29 17:28:41 -0700173 return false;
174 }
175
176 case AMOTION_EVENT_ACTION_HOVER_EXIT: {
Harry Cutts33476232023-01-30 19:57:29 +0000177 ssize_t index = findMotionMemento(entry, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700178 if (index >= 0) {
179 mMotionMementos.erase(mMotionMementos.begin() + index);
180 return true;
181 }
Siarhei Vishniakouc94dafe2023-05-26 10:24:19 -0700182
Garfield Tane84e6f92019-08-29 17:28:41 -0700183 return false;
184 }
185
186 case AMOTION_EVENT_ACTION_HOVER_ENTER:
187 case AMOTION_EVENT_ACTION_HOVER_MOVE: {
Harry Cutts33476232023-01-30 19:57:29 +0000188 ssize_t index = findMotionMemento(entry, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700189 if (index >= 0) {
190 mMotionMementos.erase(mMotionMementos.begin() + index);
191 }
Harry Cutts33476232023-01-30 19:57:29 +0000192 addMotionMemento(entry, flags, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700193 return true;
194 }
195
196 default:
197 return true;
198 }
199}
200
Siarhei Vishniakoue9ef6bc2023-12-21 19:47:20 -0800201std::optional<std::pair<std::vector<PointerProperties>, std::vector<PointerCoords>>>
202InputState::getPointersOfLastEvent(const MotionEntry& entry, bool hovering) const {
203 ssize_t index = findMotionMemento(entry, hovering);
204 if (index == -1) {
205 return std::nullopt;
206 }
207 return std::make_pair(mMotionMementos[index].pointerProperties,
208 mMotionMementos[index].pointerCoords);
209}
210
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700211ssize_t InputState::findKeyMemento(const KeyEntry& entry) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700212 for (size_t i = 0; i < mKeyMementos.size(); i++) {
213 const KeyMemento& memento = mKeyMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700214 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
215 memento.displayId == entry.displayId && memento.keyCode == entry.keyCode &&
216 memento.scanCode == entry.scanCode) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700217 return i;
218 }
219 }
220 return -1;
221}
222
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700223ssize_t InputState::findMotionMemento(const MotionEntry& entry, bool hovering) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700224 for (size_t i = 0; i < mMotionMementos.size(); i++) {
225 const MotionMemento& memento = mMotionMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700226 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
227 memento.displayId == entry.displayId && memento.hovering == hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700228 return i;
229 }
230 }
231 return -1;
232}
233
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700234void InputState::addKeyMemento(const KeyEntry& entry, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700235 KeyMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700236 memento.deviceId = entry.deviceId;
237 memento.source = entry.source;
238 memento.displayId = entry.displayId;
239 memento.keyCode = entry.keyCode;
240 memento.scanCode = entry.scanCode;
241 memento.metaState = entry.metaState;
Garfield Tane84e6f92019-08-29 17:28:41 -0700242 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700243 memento.downTime = entry.downTime;
244 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700245 mKeyMementos.push_back(memento);
246}
247
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700248void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700249 MotionMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700250 memento.deviceId = entry.deviceId;
251 memento.source = entry.source;
252 memento.displayId = entry.displayId;
Garfield Tane84e6f92019-08-29 17:28:41 -0700253 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700254 memento.xPrecision = entry.xPrecision;
255 memento.yPrecision = entry.yPrecision;
256 memento.xCursorPosition = entry.xCursorPosition;
257 memento.yCursorPosition = entry.yCursorPosition;
258 memento.downTime = entry.downTime;
Garfield Tane84e6f92019-08-29 17:28:41 -0700259 memento.setPointers(entry);
260 memento.hovering = hovering;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700261 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700262 mMotionMementos.push_back(memento);
263}
264
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700265void InputState::MotionMemento::setPointers(const MotionEntry& entry) {
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700266 pointerProperties.clear();
267 pointerCoords.clear();
268
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700269 for (uint32_t i = 0; i < entry.getPointerCount(); i++) {
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800270 if (MotionEvent::getActionMasked(entry.action) == AMOTION_EVENT_ACTION_POINTER_UP) {
271 // In POINTER_UP events, the pointer is leaving. Since the action is not stored,
272 // this departing pointer should not be recorded.
273 const uint8_t actionIndex = MotionEvent::getActionIndex(entry.action);
274 if (i == actionIndex) {
275 continue;
276 }
277 }
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700278 pointerProperties.push_back(entry.pointerProperties[i]);
279 pointerCoords.push_back(entry.pointerCoords[i]);
Garfield Tane84e6f92019-08-29 17:28:41 -0700280 }
281}
282
Svet Ganov5d3bc372020-01-26 23:11:07 -0800283void InputState::MotionMemento::mergePointerStateTo(MotionMemento& other) const {
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700284 for (uint32_t i = 0; i < getPointerCount(); i++) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800285 if (other.firstNewPointerIdx < 0) {
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700286 other.firstNewPointerIdx = other.getPointerCount();
Svet Ganov5d3bc372020-01-26 23:11:07 -0800287 }
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700288 other.pointerProperties.push_back(pointerProperties[i]);
289 other.pointerCoords.push_back(pointerCoords[i]);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800290 }
291}
292
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700293size_t InputState::MotionMemento::getPointerCount() const {
294 return pointerProperties.size();
295}
296
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000297bool InputState::shouldCancelPreviousStream(const MotionEntry& motionEntry) const {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700298 if (!isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER)) {
299 // This is a focus-dispatched event that should not affect the previous stream.
300 return false;
301 }
302
303 // New MotionEntry pointer event is coming in.
304
305 // If this is a new gesture, and it's from a different device, then, in general, we will cancel
306 // the current gesture.
307 // However, because stylus should be preferred over touch, we need to treat some cases in a
308 // special way.
309 if (mMotionMementos.empty()) {
310 // There is no ongoing pointer gesture, so there is nothing to cancel
311 return false;
312 }
313
314 const MotionMemento& lastMemento = mMotionMementos.back();
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000315 const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700316
317 // For compatibility, only one input device can be active at a time in the same window.
318 if (lastMemento.deviceId == motionEntry.deviceId) {
319 // In general, the same device should produce self-consistent streams so nothing needs to
320 // be canceled. But there is one exception:
321 // Sometimes ACTION_DOWN is received without a corresponding HOVER_EXIT. To account for
322 // that, cancel the previous hovering stream
323 if (actionMasked == AMOTION_EVENT_ACTION_DOWN && lastMemento.hovering) {
324 return true;
325 }
326
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700327 // If the stream changes its source, just cancel the current gesture to be safe. It's
328 // possible that the app isn't handling source changes properly
329 if (motionEntry.source != lastMemento.source) {
330 LOG(INFO) << "Canceling stream: last source was "
331 << inputEventSourceToString(lastMemento.source) << " and new event is "
332 << motionEntry;
333 return true;
334 }
335
336 // If the injection is happening into two different displays, the same injected device id
337 // could be going into both. And at this time, if mirroring is active, the same connection
338 // would receive different events from each display. Since the TouchStates are per-display,
339 // it's unlikely that those two streams would be consistent with each other. Therefore,
340 // cancel the previous gesture if the display id changes.
341 if (motionEntry.displayId != lastMemento.displayId) {
Siarhei Vishniakouccf845a2024-04-18 16:46:32 +0000342 LOG(INFO) << "Canceling stream: last displayId was " << lastMemento.displayId
343 << " and new event is " << motionEntry;
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700344 return true;
345 }
346
347 return false;
348 }
349
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700350 if (!input_flags::enable_multi_device_same_window_stream()) {
351 if (isStylusEvent(lastMemento.source, lastMemento.pointerProperties)) {
352 // A stylus is already active.
353 if (isStylusEvent(motionEntry.source, motionEntry.pointerProperties) &&
354 actionMasked == AMOTION_EVENT_ACTION_DOWN) {
355 // If this new event is from a different device, then cancel the old
356 // stylus and allow the new stylus to take over, but only if it's going down.
357 // Otherwise, they will start to race each other.
358 return true;
359 }
360
361 // Keep the current stylus gesture.
362 return false;
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700363 }
364
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700365 // Cancel the current gesture if this is a start of a new gesture from a new device.
366 if (actionMasked == AMOTION_EVENT_ACTION_DOWN ||
367 actionMasked == AMOTION_EVENT_ACTION_HOVER_ENTER) {
368 return true;
369 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700370 }
371 // By default, don't cancel any events.
372 return false;
373}
374
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000375std::unique_ptr<EventEntry> InputState::cancelConflictingInputStream(
376 const MotionEntry& motionEntry) {
377 if (!shouldCancelPreviousStream(motionEntry)) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700378 return {};
379 }
380
381 const MotionMemento& memento = mMotionMementos.back();
382
383 // Cancel the last device stream
384 std::unique_ptr<MotionEntry> cancelEntry =
385 createCancelEntryForMemento(memento, motionEntry.eventTime);
386
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000387 if (!trackMotion(*cancelEntry, cancelEntry->flags)) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700388 LOG(FATAL) << "Generated inconsistent cancel event!";
389 }
390 return cancelEntry;
391}
392
393std::unique_ptr<MotionEntry> InputState::createCancelEntryForMemento(const MotionMemento& memento,
394 nsecs_t eventTime) const {
395 const int32_t action =
396 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
397 int32_t flags = memento.flags;
398 if (action == AMOTION_EVENT_ACTION_CANCEL) {
399 flags |= AMOTION_EVENT_FLAG_CANCELED;
400 }
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000401 return std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
402 eventTime, memento.deviceId, memento.source,
403 memento.displayId, memento.policyFlags, action,
404 /*actionButton=*/0, flags, AMETA_NONE,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700405 /*buttonState=*/0, MotionClassification::NONE,
406 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
407 memento.yPrecision, memento.xCursorPosition,
408 memento.yCursorPosition, memento.downTime,
409 memento.pointerProperties, memento.pointerCoords);
410}
411
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700412std::vector<std::unique_ptr<EventEntry>> InputState::synthesizeCancelationEvents(
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700413 nsecs_t currentTime, const CancelationOptions& options) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700414 std::vector<std::unique_ptr<EventEntry>> events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700415 for (KeyMemento& memento : mKeyMementos) {
416 if (shouldCancelKey(memento, options)) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700417 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000418 std::make_unique<KeyEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
419 currentTime, memento.deviceId, memento.source,
420 memento.displayId, memento.policyFlags,
421 AKEY_EVENT_ACTION_UP,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700422 memento.flags | AKEY_EVENT_FLAG_CANCELED,
423 memento.keyCode, memento.scanCode, memento.metaState,
Harry Cutts33476232023-01-30 19:57:29 +0000424 /*repeatCount=*/0, memento.downTime));
Garfield Tane84e6f92019-08-29 17:28:41 -0700425 }
426 }
427
428 for (const MotionMemento& memento : mMotionMementos) {
429 if (shouldCancelMotion(memento, options)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000430 if (options.pointerIds == std::nullopt) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700431 events.push_back(createCancelEntryForMemento(memento, currentTime));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000432 } else {
433 std::vector<std::unique_ptr<MotionEntry>> pointerCancelEvents =
434 synthesizeCancelationEventsForPointers(memento, options.pointerIds.value(),
435 currentTime);
436 events.insert(events.end(), std::make_move_iterator(pointerCancelEvents.begin()),
437 std::make_move_iterator(pointerCancelEvents.end()));
438 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700439 }
440 }
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700441 return events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700442}
443
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700444std::vector<std::unique_ptr<EventEntry>> InputState::synthesizePointerDownEvents(
445 nsecs_t currentTime) {
446 std::vector<std::unique_ptr<EventEntry>> events;
Svet Ganov5d3bc372020-01-26 23:11:07 -0800447 for (MotionMemento& memento : mMotionMementos) {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700448 if (!isFromSource(memento.source, AINPUT_SOURCE_CLASS_POINTER)) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800449 continue;
450 }
451
452 if (memento.firstNewPointerIdx < 0) {
453 continue;
454 }
455
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700456 std::vector<PointerProperties> pointerProperties;
457 std::vector<PointerCoords> pointerCoords;
Svet Ganov5d3bc372020-01-26 23:11:07 -0800458
459 // We will deliver all pointers the target already knows about
460 for (uint32_t i = 0; i < static_cast<uint32_t>(memento.firstNewPointerIdx); i++) {
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700461 pointerProperties.push_back(memento.pointerProperties[i]);
462 pointerCoords.push_back(memento.pointerCoords[i]);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800463 }
464
465 // We will send explicit events for all pointers the target doesn't know about
466 for (uint32_t i = static_cast<uint32_t>(memento.firstNewPointerIdx);
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700467 i < memento.getPointerCount(); i++) {
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700468 pointerProperties.push_back(memento.pointerProperties[i]);
469 pointerCoords.push_back(memento.pointerCoords[i]);
470
471 const size_t pointerCount = pointerProperties.size();
Svet Ganov5d3bc372020-01-26 23:11:07 -0800472
473 // Down only if the first pointer, pointer down otherwise
474 const int32_t action = (pointerCount <= 1)
475 ? AMOTION_EVENT_ACTION_DOWN
476 : AMOTION_EVENT_ACTION_POINTER_DOWN
477 | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
478
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700479 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000480 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
481 currentTime, memento.deviceId, memento.source,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700482 memento.displayId, memento.policyFlags, action,
Harry Cutts33476232023-01-30 19:57:29 +0000483 /*actionButton=*/0, memento.flags, AMETA_NONE,
484 /*buttonState=*/0, MotionClassification::NONE,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700485 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
486 memento.yPrecision, memento.xCursorPosition,
487 memento.yCursorPosition, memento.downTime,
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700488 pointerProperties, pointerCoords));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800489 }
490
491 memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
492 }
493
494 return events;
495}
496
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000497std::vector<std::unique_ptr<MotionEntry>> InputState::synthesizeCancelationEventsForPointers(
Siarhei Vishniakou8a878352023-01-30 14:05:01 -0800498 const MotionMemento& memento, std::bitset<MAX_POINTER_ID + 1> pointerIds,
499 nsecs_t currentTime) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000500 std::vector<std::unique_ptr<MotionEntry>> events;
501 std::vector<uint32_t> canceledPointerIndices;
502 std::vector<PointerProperties> pointerProperties(MAX_POINTERS);
503 std::vector<PointerCoords> pointerCoords(MAX_POINTERS);
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700504 for (uint32_t pointerIdx = 0; pointerIdx < memento.getPointerCount(); pointerIdx++) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000505 uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
Siarhei Vishniakou73e6d372023-07-06 18:07:21 -0700506 pointerProperties[pointerIdx] = memento.pointerProperties[pointerIdx];
507 pointerCoords[pointerIdx] = memento.pointerCoords[pointerIdx];
Siarhei Vishniakou8a878352023-01-30 14:05:01 -0800508 if (pointerIds.test(pointerId)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000509 canceledPointerIndices.push_back(pointerIdx);
510 }
511 }
512
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700513 if (canceledPointerIndices.size() == memento.getPointerCount()) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000514 const int32_t action =
515 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800516 int32_t flags = memento.flags;
517 if (action == AMOTION_EVENT_ACTION_CANCEL) {
518 flags |= AMOTION_EVENT_FLAG_CANCELED;
519 }
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000520 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000521 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
522 currentTime, memento.deviceId, memento.source,
523 memento.displayId, memento.policyFlags, action,
524 /*actionButton=*/0, flags, AMETA_NONE,
525 /*buttonState=*/0, MotionClassification::NONE,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000526 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
527 memento.yPrecision, memento.xCursorPosition,
528 memento.yCursorPosition, memento.downTime,
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700529 memento.pointerProperties, memento.pointerCoords));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000530 } else {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800531 // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000532 // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
533 // previously canceled pointers from PointerProperties and PointerCoords, and update
534 // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
535 // can just slide the remaining pointers to the beginning of the array when a pointer is
536 // canceled.
537 std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
538 std::greater<uint32_t>());
539
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700540 uint32_t pointerCount = memento.getPointerCount();
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000541 for (const uint32_t pointerIdx : canceledPointerIndices) {
542 const int32_t action = pointerCount == 1 ? AMOTION_EVENT_ACTION_CANCEL
543 : AMOTION_EVENT_ACTION_POINTER_UP |
544 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
545 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000546 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
547 currentTime, memento.deviceId, memento.source,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000548 memento.displayId, memento.policyFlags, action,
Harry Cutts33476232023-01-30 19:57:29 +0000549 /*actionButton=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000550 memento.flags | AMOTION_EVENT_FLAG_CANCELED,
Harry Cutts33476232023-01-30 19:57:29 +0000551 AMETA_NONE, /*buttonState=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000552 MotionClassification::NONE,
553 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
554 memento.yPrecision, memento.xCursorPosition,
555 memento.yCursorPosition, memento.downTime,
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700556 pointerProperties, pointerCoords));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000557
558 // Cleanup pointer information
559 pointerProperties.erase(pointerProperties.begin() + pointerIdx);
560 pointerCoords.erase(pointerCoords.begin() + pointerIdx);
561 pointerCount--;
562 }
563 }
564 return events;
565}
566
Garfield Tane84e6f92019-08-29 17:28:41 -0700567void InputState::clear() {
568 mKeyMementos.clear();
569 mMotionMementos.clear();
570 mFallbackKeys.clear();
571}
572
Svet Ganov5d3bc372020-01-26 23:11:07 -0800573void InputState::mergePointerStateTo(InputState& other) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700574 for (size_t i = 0; i < mMotionMementos.size(); i++) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800575 MotionMemento& memento = mMotionMementos[i];
576 // Since we support split pointers we need to merge touch events
577 // from the same source + device + screen.
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700578 if (isFromSource(memento.source, AINPUT_SOURCE_CLASS_POINTER)) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800579 bool merged = false;
580 for (size_t j = 0; j < other.mMotionMementos.size(); j++) {
581 MotionMemento& otherMemento = other.mMotionMementos[j];
Garfield Tane84e6f92019-08-29 17:28:41 -0700582 if (memento.deviceId == otherMemento.deviceId &&
583 memento.source == otherMemento.source &&
584 memento.displayId == otherMemento.displayId) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800585 memento.mergePointerStateTo(otherMemento);
586 merged = true;
587 break;
Garfield Tane84e6f92019-08-29 17:28:41 -0700588 }
589 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800590 if (!merged) {
591 memento.firstNewPointerIdx = 0;
592 other.mMotionMementos.push_back(memento);
593 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700594 }
595 }
596}
597
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -0700598std::optional<int32_t> InputState::getFallbackKey(int32_t originalKeyCode) {
599 auto it = mFallbackKeys.find(originalKeyCode);
600 if (it == mFallbackKeys.end()) {
601 return {};
602 }
603 return it->second;
Garfield Tane84e6f92019-08-29 17:28:41 -0700604}
605
606void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -0700607 mFallbackKeys.insert_or_assign(originalKeyCode, fallbackKeyCode);
Garfield Tane84e6f92019-08-29 17:28:41 -0700608}
609
610void InputState::removeFallbackKey(int32_t originalKeyCode) {
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -0700611 mFallbackKeys.erase(originalKeyCode);
Garfield Tane84e6f92019-08-29 17:28:41 -0700612}
613
614bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
615 if (options.keyCode && memento.keyCode != options.keyCode.value()) {
616 return false;
617 }
618
619 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
620 return false;
621 }
622
623 if (options.displayId && memento.displayId != options.displayId.value()) {
624 return false;
625 }
626
627 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000628 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
629 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700630 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000631 case CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700632 return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
633 default:
634 return false;
635 }
636}
637
638bool InputState::shouldCancelMotion(const MotionMemento& memento,
639 const CancelationOptions& options) {
640 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
641 return false;
642 }
643
644 if (options.displayId && memento.displayId != options.displayId.value()) {
645 return false;
646 }
647
648 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000649 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700650 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000651 case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700652 return memento.source & AINPUT_SOURCE_CLASS_POINTER;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000653 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700654 return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
655 default:
656 return false;
657 }
658}
659
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700660std::ostream& operator<<(std::ostream& out, const InputState& state) {
661 if (!state.mMotionMementos.empty()) {
662 out << "mMotionMementos: ";
663 for (const InputState::MotionMemento& memento : state.mMotionMementos) {
664 out << "{deviceId= " << memento.deviceId << ", hovering=" << memento.hovering << "}, ";
665 }
666 }
667 return out;
668}
669
Garfield Tane84e6f92019-08-29 17:28:41 -0700670} // namespace android::inputdispatcher