blob: 02bc3680bf8b60fc1ab1acd73a38bbcbb55312d9 [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
Siarhei Vishniakou7e2f8f12023-07-11 10:51:20 -070031bool InputState::isHovering(DeviceId deviceId, uint32_t source, int32_t displayId) const {
Garfield Tane84e6f92019-08-29 17:28:41 -070032 for (const MotionMemento& memento : mMotionMementos) {
33 if (memento.deviceId == deviceId && memento.source == source &&
34 memento.displayId == displayId && memento.hovering) {
35 return true;
36 }
37 }
38 return false;
39}
40
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +000041bool InputState::trackKey(const KeyEntry& entry, int32_t flags) {
42 switch (entry.action) {
Garfield Tane84e6f92019-08-29 17:28:41 -070043 case AKEY_EVENT_ACTION_UP: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070044 if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -070045 std::erase_if(mFallbackKeys,
46 [&entry](const auto& item) { return item.second == entry.keyCode; });
Garfield Tane84e6f92019-08-29 17:28:41 -070047 }
48 ssize_t index = findKeyMemento(entry);
49 if (index >= 0) {
50 mKeyMementos.erase(mKeyMementos.begin() + index);
51 return true;
52 }
53 /* FIXME: We can't just drop the key up event because that prevents creating
54 * popup windows that are automatically shown when a key is held and then
55 * dismissed when the key is released. The problem is that the popup will
56 * not have received the original key down, so the key up will be considered
57 * to be inconsistent with its observed state. We could perhaps handle this
58 * by synthesizing a key down but that will cause other problems.
59 *
60 * So for now, allow inconsistent key up events to be dispatched.
61 *
62 #if DEBUG_OUTBOUND_EVENT_DETAILS
63 ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
64 "keyCode=%d, scanCode=%d",
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070065 entry.deviceId, entry.source, entry.keyCode, entry.scanCode);
Garfield Tane84e6f92019-08-29 17:28:41 -070066 #endif
67 return false;
68 */
69 return true;
70 }
71
72 case AKEY_EVENT_ACTION_DOWN: {
73 ssize_t index = findKeyMemento(entry);
74 if (index >= 0) {
75 mKeyMementos.erase(mKeyMementos.begin() + index);
76 }
77 addKeyMemento(entry, flags);
78 return true;
79 }
80
81 default:
82 return true;
83 }
84}
85
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070086/**
87 * Return:
88 * true if the incoming event was correctly tracked,
89 * false if the incoming event should be dropped.
90 */
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +000091bool InputState::trackMotion(const MotionEntry& entry, int32_t flags) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070092 // Don't track non-pointer events
93 if (!isFromSource(entry.source, AINPUT_SOURCE_CLASS_POINTER)) {
94 // This is a focus-dispatched event; we don't track its state.
95 return true;
96 }
97
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070098 if (!input_flags::enable_multi_device_same_window_stream()) {
99 if (!mMotionMementos.empty()) {
100 const MotionMemento& lastMemento = mMotionMementos.back();
101 if (isStylusEvent(lastMemento.source, lastMemento.pointerProperties) &&
102 !isStylusEvent(entry.source, entry.pointerProperties)) {
103 // We already have a stylus stream, and the new event is not from stylus.
104 return false;
105 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700106 }
107 }
108
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000109 int32_t actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
Garfield Tane84e6f92019-08-29 17:28:41 -0700110 switch (actionMasked) {
111 case AMOTION_EVENT_ACTION_UP:
112 case AMOTION_EVENT_ACTION_CANCEL: {
Harry Cutts33476232023-01-30 19:57:29 +0000113 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700114 if (index >= 0) {
115 mMotionMementos.erase(mMotionMementos.begin() + index);
116 return true;
117 }
Siarhei Vishniakouc94dafe2023-05-26 10:24:19 -0700118
Garfield Tane84e6f92019-08-29 17:28:41 -0700119 return false;
120 }
121
122 case AMOTION_EVENT_ACTION_DOWN: {
Harry Cutts33476232023-01-30 19:57:29 +0000123 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700124 if (index >= 0) {
125 mMotionMementos.erase(mMotionMementos.begin() + index);
126 }
Harry Cutts33476232023-01-30 19:57:29 +0000127 addMotionMemento(entry, flags, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700128 return true;
129 }
130
131 case AMOTION_EVENT_ACTION_POINTER_UP:
132 case AMOTION_EVENT_ACTION_POINTER_DOWN:
133 case AMOTION_EVENT_ACTION_MOVE: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700134 if (entry.source & AINPUT_SOURCE_CLASS_NAVIGATION) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700135 // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need
136 // to generate cancellation events for these since they're based in relative rather
137 // than absolute units.
138 return true;
139 }
140
Harry Cutts33476232023-01-30 19:57:29 +0000141 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700142
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700143 if (entry.source & AINPUT_SOURCE_CLASS_JOYSTICK) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700144 // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
145 // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral.
146 // Any other value and we need to track the motion so we can send cancellation
147 // events for anything generating fallback events (e.g. DPad keys for joystick
148 // movements).
149 if (index >= 0) {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700150 if (entry.pointerCoords[0].isEmpty()) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700151 mMotionMementos.erase(mMotionMementos.begin() + index);
152 } else {
153 MotionMemento& memento = mMotionMementos[index];
154 memento.setPointers(entry);
155 }
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700156 } else if (!entry.pointerCoords[0].isEmpty()) {
Harry Cutts33476232023-01-30 19:57:29 +0000157 addMotionMemento(entry, flags, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700158 }
159
160 // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
161 return true;
162 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800163
Garfield Tane84e6f92019-08-29 17:28:41 -0700164 if (index >= 0) {
165 MotionMemento& memento = mMotionMementos[index];
Svet Ganov5d3bc372020-01-26 23:11:07 -0800166 if (memento.firstNewPointerIdx < 0) {
167 memento.setPointers(entry);
168 return true;
169 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700170 }
Siarhei Vishniakouc94dafe2023-05-26 10:24:19 -0700171
Garfield Tane84e6f92019-08-29 17:28:41 -0700172 return false;
173 }
174
175 case AMOTION_EVENT_ACTION_HOVER_EXIT: {
Harry Cutts33476232023-01-30 19:57:29 +0000176 ssize_t index = findMotionMemento(entry, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700177 if (index >= 0) {
178 mMotionMementos.erase(mMotionMementos.begin() + index);
179 return true;
180 }
Siarhei Vishniakouc94dafe2023-05-26 10:24:19 -0700181
Garfield Tane84e6f92019-08-29 17:28:41 -0700182 return false;
183 }
184
185 case AMOTION_EVENT_ACTION_HOVER_ENTER:
186 case AMOTION_EVENT_ACTION_HOVER_MOVE: {
Harry Cutts33476232023-01-30 19:57:29 +0000187 ssize_t index = findMotionMemento(entry, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700188 if (index >= 0) {
189 mMotionMementos.erase(mMotionMementos.begin() + index);
190 }
Harry Cutts33476232023-01-30 19:57:29 +0000191 addMotionMemento(entry, flags, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700192 return true;
193 }
194
195 default:
196 return true;
197 }
198}
199
Siarhei Vishniakoue9ef6bc2023-12-21 19:47:20 -0800200std::optional<std::pair<std::vector<PointerProperties>, std::vector<PointerCoords>>>
201InputState::getPointersOfLastEvent(const MotionEntry& entry, bool hovering) const {
202 ssize_t index = findMotionMemento(entry, hovering);
203 if (index == -1) {
204 return std::nullopt;
205 }
206 return std::make_pair(mMotionMementos[index].pointerProperties,
207 mMotionMementos[index].pointerCoords);
208}
209
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700210ssize_t InputState::findKeyMemento(const KeyEntry& entry) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700211 for (size_t i = 0; i < mKeyMementos.size(); i++) {
212 const KeyMemento& memento = mKeyMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700213 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
214 memento.displayId == entry.displayId && memento.keyCode == entry.keyCode &&
215 memento.scanCode == entry.scanCode) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700216 return i;
217 }
218 }
219 return -1;
220}
221
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700222ssize_t InputState::findMotionMemento(const MotionEntry& entry, bool hovering) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700223 for (size_t i = 0; i < mMotionMementos.size(); i++) {
224 const MotionMemento& memento = mMotionMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700225 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
226 memento.displayId == entry.displayId && memento.hovering == hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700227 return i;
228 }
229 }
230 return -1;
231}
232
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700233void InputState::addKeyMemento(const KeyEntry& entry, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700234 KeyMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700235 memento.deviceId = entry.deviceId;
236 memento.source = entry.source;
237 memento.displayId = entry.displayId;
238 memento.keyCode = entry.keyCode;
239 memento.scanCode = entry.scanCode;
240 memento.metaState = entry.metaState;
Garfield Tane84e6f92019-08-29 17:28:41 -0700241 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700242 memento.downTime = entry.downTime;
243 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700244 mKeyMementos.push_back(memento);
245}
246
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700247void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700248 MotionMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700249 memento.deviceId = entry.deviceId;
250 memento.source = entry.source;
251 memento.displayId = entry.displayId;
Garfield Tane84e6f92019-08-29 17:28:41 -0700252 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700253 memento.xPrecision = entry.xPrecision;
254 memento.yPrecision = entry.yPrecision;
255 memento.xCursorPosition = entry.xCursorPosition;
256 memento.yCursorPosition = entry.yCursorPosition;
257 memento.downTime = entry.downTime;
Garfield Tane84e6f92019-08-29 17:28:41 -0700258 memento.setPointers(entry);
259 memento.hovering = hovering;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700260 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700261 mMotionMementos.push_back(memento);
262}
263
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700264void InputState::MotionMemento::setPointers(const MotionEntry& entry) {
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700265 pointerProperties.clear();
266 pointerCoords.clear();
267
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700268 for (uint32_t i = 0; i < entry.getPointerCount(); i++) {
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800269 if (MotionEvent::getActionMasked(entry.action) == AMOTION_EVENT_ACTION_POINTER_UP) {
270 // In POINTER_UP events, the pointer is leaving. Since the action is not stored,
271 // this departing pointer should not be recorded.
272 const uint8_t actionIndex = MotionEvent::getActionIndex(entry.action);
273 if (i == actionIndex) {
274 continue;
275 }
276 }
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700277 pointerProperties.push_back(entry.pointerProperties[i]);
278 pointerCoords.push_back(entry.pointerCoords[i]);
Garfield Tane84e6f92019-08-29 17:28:41 -0700279 }
280}
281
Svet Ganov5d3bc372020-01-26 23:11:07 -0800282void InputState::MotionMemento::mergePointerStateTo(MotionMemento& other) const {
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700283 for (uint32_t i = 0; i < getPointerCount(); i++) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800284 if (other.firstNewPointerIdx < 0) {
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700285 other.firstNewPointerIdx = other.getPointerCount();
Svet Ganov5d3bc372020-01-26 23:11:07 -0800286 }
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700287 other.pointerProperties.push_back(pointerProperties[i]);
288 other.pointerCoords.push_back(pointerCoords[i]);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800289 }
290}
291
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700292size_t InputState::MotionMemento::getPointerCount() const {
293 return pointerProperties.size();
294}
295
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000296bool InputState::shouldCancelPreviousStream(const MotionEntry& motionEntry) const {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700297 if (!isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER)) {
298 // This is a focus-dispatched event that should not affect the previous stream.
299 return false;
300 }
301
302 // New MotionEntry pointer event is coming in.
303
304 // If this is a new gesture, and it's from a different device, then, in general, we will cancel
305 // the current gesture.
306 // However, because stylus should be preferred over touch, we need to treat some cases in a
307 // special way.
308 if (mMotionMementos.empty()) {
309 // There is no ongoing pointer gesture, so there is nothing to cancel
310 return false;
311 }
312
313 const MotionMemento& lastMemento = mMotionMementos.back();
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000314 const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700315
316 // For compatibility, only one input device can be active at a time in the same window.
317 if (lastMemento.deviceId == motionEntry.deviceId) {
318 // In general, the same device should produce self-consistent streams so nothing needs to
319 // be canceled. But there is one exception:
320 // Sometimes ACTION_DOWN is received without a corresponding HOVER_EXIT. To account for
321 // that, cancel the previous hovering stream
322 if (actionMasked == AMOTION_EVENT_ACTION_DOWN && lastMemento.hovering) {
323 return true;
324 }
325
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700326 // If the stream changes its source, just cancel the current gesture to be safe. It's
327 // possible that the app isn't handling source changes properly
328 if (motionEntry.source != lastMemento.source) {
329 LOG(INFO) << "Canceling stream: last source was "
330 << inputEventSourceToString(lastMemento.source) << " and new event is "
331 << motionEntry;
332 return true;
333 }
334
335 // If the injection is happening into two different displays, the same injected device id
336 // could be going into both. And at this time, if mirroring is active, the same connection
337 // would receive different events from each display. Since the TouchStates are per-display,
338 // it's unlikely that those two streams would be consistent with each other. Therefore,
339 // cancel the previous gesture if the display id changes.
340 if (motionEntry.displayId != lastMemento.displayId) {
Siarhei Vishniakouccf845a2024-04-18 16:46:32 +0000341 LOG(INFO) << "Canceling stream: last displayId was " << lastMemento.displayId
342 << " and new event is " << motionEntry;
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700343 return true;
344 }
345
346 return false;
347 }
348
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700349 if (!input_flags::enable_multi_device_same_window_stream()) {
350 if (isStylusEvent(lastMemento.source, lastMemento.pointerProperties)) {
351 // A stylus is already active.
352 if (isStylusEvent(motionEntry.source, motionEntry.pointerProperties) &&
353 actionMasked == AMOTION_EVENT_ACTION_DOWN) {
354 // If this new event is from a different device, then cancel the old
355 // stylus and allow the new stylus to take over, but only if it's going down.
356 // Otherwise, they will start to race each other.
357 return true;
358 }
359
360 // Keep the current stylus gesture.
361 return false;
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700362 }
363
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700364 // Cancel the current gesture if this is a start of a new gesture from a new device.
365 if (actionMasked == AMOTION_EVENT_ACTION_DOWN ||
366 actionMasked == AMOTION_EVENT_ACTION_HOVER_ENTER) {
367 return true;
368 }
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700369 }
370 // By default, don't cancel any events.
371 return false;
372}
373
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000374std::unique_ptr<EventEntry> InputState::cancelConflictingInputStream(
375 const MotionEntry& motionEntry) {
376 if (!shouldCancelPreviousStream(motionEntry)) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700377 return {};
378 }
379
380 const MotionMemento& memento = mMotionMementos.back();
381
382 // Cancel the last device stream
383 std::unique_ptr<MotionEntry> cancelEntry =
384 createCancelEntryForMemento(memento, motionEntry.eventTime);
385
Prabir Pradhan2a2da1d2023-11-03 02:16:20 +0000386 if (!trackMotion(*cancelEntry, cancelEntry->flags)) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700387 LOG(FATAL) << "Generated inconsistent cancel event!";
388 }
389 return cancelEntry;
390}
391
392std::unique_ptr<MotionEntry> InputState::createCancelEntryForMemento(const MotionMemento& memento,
393 nsecs_t eventTime) const {
394 const int32_t action =
395 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
396 int32_t flags = memento.flags;
397 if (action == AMOTION_EVENT_ACTION_CANCEL) {
398 flags |= AMOTION_EVENT_FLAG_CANCELED;
399 }
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000400 return std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
401 eventTime, memento.deviceId, memento.source,
402 memento.displayId, memento.policyFlags, action,
403 /*actionButton=*/0, flags, AMETA_NONE,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700404 /*buttonState=*/0, MotionClassification::NONE,
405 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
406 memento.yPrecision, memento.xCursorPosition,
407 memento.yCursorPosition, memento.downTime,
408 memento.pointerProperties, memento.pointerCoords);
409}
410
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700411std::vector<std::unique_ptr<EventEntry>> InputState::synthesizeCancelationEvents(
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700412 nsecs_t currentTime, const CancelationOptions& options) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700413 std::vector<std::unique_ptr<EventEntry>> events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700414 for (KeyMemento& memento : mKeyMementos) {
415 if (shouldCancelKey(memento, options)) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700416 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000417 std::make_unique<KeyEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
418 currentTime, memento.deviceId, memento.source,
419 memento.displayId, memento.policyFlags,
420 AKEY_EVENT_ACTION_UP,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700421 memento.flags | AKEY_EVENT_FLAG_CANCELED,
422 memento.keyCode, memento.scanCode, memento.metaState,
Harry Cutts33476232023-01-30 19:57:29 +0000423 /*repeatCount=*/0, memento.downTime));
Garfield Tane84e6f92019-08-29 17:28:41 -0700424 }
425 }
426
427 for (const MotionMemento& memento : mMotionMementos) {
428 if (shouldCancelMotion(memento, options)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000429 if (options.pointerIds == std::nullopt) {
Siarhei Vishniakou2899c552023-07-10 18:20:46 -0700430 events.push_back(createCancelEntryForMemento(memento, currentTime));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000431 } else {
432 std::vector<std::unique_ptr<MotionEntry>> pointerCancelEvents =
433 synthesizeCancelationEventsForPointers(memento, options.pointerIds.value(),
434 currentTime);
435 events.insert(events.end(), std::make_move_iterator(pointerCancelEvents.begin()),
436 std::make_move_iterator(pointerCancelEvents.end()));
437 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700438 }
439 }
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700440 return events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700441}
442
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700443std::vector<std::unique_ptr<EventEntry>> InputState::synthesizePointerDownEvents(
444 nsecs_t currentTime) {
445 std::vector<std::unique_ptr<EventEntry>> events;
Svet Ganov5d3bc372020-01-26 23:11:07 -0800446 for (MotionMemento& memento : mMotionMementos) {
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700447 if (!isFromSource(memento.source, AINPUT_SOURCE_CLASS_POINTER)) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800448 continue;
449 }
450
451 if (memento.firstNewPointerIdx < 0) {
452 continue;
453 }
454
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700455 std::vector<PointerProperties> pointerProperties;
456 std::vector<PointerCoords> pointerCoords;
Svet Ganov5d3bc372020-01-26 23:11:07 -0800457
458 // We will deliver all pointers the target already knows about
459 for (uint32_t i = 0; i < static_cast<uint32_t>(memento.firstNewPointerIdx); i++) {
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700460 pointerProperties.push_back(memento.pointerProperties[i]);
461 pointerCoords.push_back(memento.pointerCoords[i]);
Svet Ganov5d3bc372020-01-26 23:11:07 -0800462 }
463
464 // We will send explicit events for all pointers the target doesn't know about
465 for (uint32_t i = static_cast<uint32_t>(memento.firstNewPointerIdx);
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700466 i < memento.getPointerCount(); i++) {
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700467 pointerProperties.push_back(memento.pointerProperties[i]);
468 pointerCoords.push_back(memento.pointerCoords[i]);
469
470 const size_t pointerCount = pointerProperties.size();
Svet Ganov5d3bc372020-01-26 23:11:07 -0800471
472 // Down only if the first pointer, pointer down otherwise
473 const int32_t action = (pointerCount <= 1)
474 ? AMOTION_EVENT_ACTION_DOWN
475 : AMOTION_EVENT_ACTION_POINTER_DOWN
476 | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
477
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700478 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000479 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
480 currentTime, memento.deviceId, memento.source,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700481 memento.displayId, memento.policyFlags, action,
Harry Cutts33476232023-01-30 19:57:29 +0000482 /*actionButton=*/0, memento.flags, AMETA_NONE,
483 /*buttonState=*/0, MotionClassification::NONE,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700484 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
485 memento.yPrecision, memento.xCursorPosition,
486 memento.yCursorPosition, memento.downTime,
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700487 pointerProperties, pointerCoords));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800488 }
489
490 memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
491 }
492
493 return events;
494}
495
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000496std::vector<std::unique_ptr<MotionEntry>> InputState::synthesizeCancelationEventsForPointers(
Siarhei Vishniakou8a878352023-01-30 14:05:01 -0800497 const MotionMemento& memento, std::bitset<MAX_POINTER_ID + 1> pointerIds,
498 nsecs_t currentTime) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000499 std::vector<std::unique_ptr<MotionEntry>> events;
500 std::vector<uint32_t> canceledPointerIndices;
501 std::vector<PointerProperties> pointerProperties(MAX_POINTERS);
502 std::vector<PointerCoords> pointerCoords(MAX_POINTERS);
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700503 for (uint32_t pointerIdx = 0; pointerIdx < memento.getPointerCount(); pointerIdx++) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000504 uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
Siarhei Vishniakou73e6d372023-07-06 18:07:21 -0700505 pointerProperties[pointerIdx] = memento.pointerProperties[pointerIdx];
506 pointerCoords[pointerIdx] = memento.pointerCoords[pointerIdx];
Siarhei Vishniakou8a878352023-01-30 14:05:01 -0800507 if (pointerIds.test(pointerId)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000508 canceledPointerIndices.push_back(pointerIdx);
509 }
510 }
511
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700512 if (canceledPointerIndices.size() == memento.getPointerCount()) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000513 const int32_t action =
514 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800515 int32_t flags = memento.flags;
516 if (action == AMOTION_EVENT_ACTION_CANCEL) {
517 flags |= AMOTION_EVENT_FLAG_CANCELED;
518 }
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000519 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000520 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
521 currentTime, memento.deviceId, memento.source,
522 memento.displayId, memento.policyFlags, action,
523 /*actionButton=*/0, flags, AMETA_NONE,
524 /*buttonState=*/0, MotionClassification::NONE,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000525 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
526 memento.yPrecision, memento.xCursorPosition,
527 memento.yCursorPosition, memento.downTime,
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700528 memento.pointerProperties, memento.pointerCoords));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000529 } else {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800530 // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000531 // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
532 // previously canceled pointers from PointerProperties and PointerCoords, and update
533 // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
534 // can just slide the remaining pointers to the beginning of the array when a pointer is
535 // canceled.
536 std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
537 std::greater<uint32_t>());
538
Siarhei Vishniakou47a02a12023-10-18 09:56:00 -0700539 uint32_t pointerCount = memento.getPointerCount();
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000540 for (const uint32_t pointerIdx : canceledPointerIndices) {
541 const int32_t action = pointerCount == 1 ? AMOTION_EVENT_ACTION_CANCEL
542 : AMOTION_EVENT_ACTION_POINTER_UP |
543 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
544 events.push_back(
Prabir Pradhana8cdbe12023-11-01 21:30:02 +0000545 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
546 currentTime, memento.deviceId, memento.source,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000547 memento.displayId, memento.policyFlags, action,
Harry Cutts33476232023-01-30 19:57:29 +0000548 /*actionButton=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000549 memento.flags | AMOTION_EVENT_FLAG_CANCELED,
Harry Cutts33476232023-01-30 19:57:29 +0000550 AMETA_NONE, /*buttonState=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000551 MotionClassification::NONE,
552 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
553 memento.yPrecision, memento.xCursorPosition,
554 memento.yCursorPosition, memento.downTime,
Siarhei Vishniakouedd61202023-10-18 11:22:40 -0700555 pointerProperties, pointerCoords));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000556
557 // Cleanup pointer information
558 pointerProperties.erase(pointerProperties.begin() + pointerIdx);
559 pointerCoords.erase(pointerCoords.begin() + pointerIdx);
560 pointerCount--;
561 }
562 }
563 return events;
564}
565
Garfield Tane84e6f92019-08-29 17:28:41 -0700566void InputState::clear() {
567 mKeyMementos.clear();
568 mMotionMementos.clear();
569 mFallbackKeys.clear();
570}
571
Svet Ganov5d3bc372020-01-26 23:11:07 -0800572void InputState::mergePointerStateTo(InputState& other) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700573 for (size_t i = 0; i < mMotionMementos.size(); i++) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800574 MotionMemento& memento = mMotionMementos[i];
575 // Since we support split pointers we need to merge touch events
576 // from the same source + device + screen.
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700577 if (isFromSource(memento.source, AINPUT_SOURCE_CLASS_POINTER)) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800578 bool merged = false;
579 for (size_t j = 0; j < other.mMotionMementos.size(); j++) {
580 MotionMemento& otherMemento = other.mMotionMementos[j];
Garfield Tane84e6f92019-08-29 17:28:41 -0700581 if (memento.deviceId == otherMemento.deviceId &&
582 memento.source == otherMemento.source &&
583 memento.displayId == otherMemento.displayId) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800584 memento.mergePointerStateTo(otherMemento);
585 merged = true;
586 break;
Garfield Tane84e6f92019-08-29 17:28:41 -0700587 }
588 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800589 if (!merged) {
590 memento.firstNewPointerIdx = 0;
591 other.mMotionMementos.push_back(memento);
592 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700593 }
594 }
595}
596
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -0700597std::optional<int32_t> InputState::getFallbackKey(int32_t originalKeyCode) {
598 auto it = mFallbackKeys.find(originalKeyCode);
599 if (it == mFallbackKeys.end()) {
600 return {};
601 }
602 return it->second;
Garfield Tane84e6f92019-08-29 17:28:41 -0700603}
604
605void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -0700606 mFallbackKeys.insert_or_assign(originalKeyCode, fallbackKeyCode);
Garfield Tane84e6f92019-08-29 17:28:41 -0700607}
608
609void InputState::removeFallbackKey(int32_t originalKeyCode) {
Siarhei Vishniakou0fe01262023-04-17 08:11:37 -0700610 mFallbackKeys.erase(originalKeyCode);
Garfield Tane84e6f92019-08-29 17:28:41 -0700611}
612
613bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
614 if (options.keyCode && memento.keyCode != options.keyCode.value()) {
615 return false;
616 }
617
618 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
619 return false;
620 }
621
622 if (options.displayId && memento.displayId != options.displayId.value()) {
623 return false;
624 }
625
626 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000627 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
628 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700629 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000630 case CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700631 return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
632 default:
633 return false;
634 }
635}
636
637bool InputState::shouldCancelMotion(const MotionMemento& memento,
638 const CancelationOptions& options) {
639 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
640 return false;
641 }
642
643 if (options.displayId && memento.displayId != options.displayId.value()) {
644 return false;
645 }
646
647 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000648 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700649 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000650 case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700651 return memento.source & AINPUT_SOURCE_CLASS_POINTER;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000652 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700653 return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
654 default:
655 return false;
656 }
657}
658
Siarhei Vishniakoud38a1e02023-07-18 11:55:17 -0700659std::ostream& operator<<(std::ostream& out, const InputState& state) {
660 if (!state.mMotionMementos.empty()) {
661 out << "mMotionMementos: ";
662 for (const InputState::MotionMemento& memento : state.mMotionMementos) {
663 out << "{deviceId= " << memento.deviceId << ", hovering=" << memento.hovering << "}, ";
664 }
665 }
666 return out;
667}
668
Garfield Tane84e6f92019-08-29 17:28:41 -0700669} // namespace android::inputdispatcher