blob: 563868d10ec751b875c5d7d489be97170110e4d0 [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
31bool InputState::isNeutral() const {
32 return mKeyMementos.empty() && mMotionMementos.empty();
33}
34
35bool InputState::isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const {
36 for (const MotionMemento& memento : mMotionMementos) {
37 if (memento.deviceId == deviceId && memento.source == source &&
38 memento.displayId == displayId && memento.hovering) {
39 return true;
40 }
41 }
42 return false;
43}
44
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070045bool InputState::trackKey(const KeyEntry& entry, int32_t action, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -070046 switch (action) {
47 case AKEY_EVENT_ACTION_UP: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070048 if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
Garfield Tane84e6f92019-08-29 17:28:41 -070049 for (size_t i = 0; i < mFallbackKeys.size();) {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070050 if (mFallbackKeys.valueAt(i) == entry.keyCode) {
Garfield Tane84e6f92019-08-29 17:28:41 -070051 mFallbackKeys.removeItemsAt(i);
52 } else {
53 i += 1;
54 }
55 }
56 }
57 ssize_t index = findKeyMemento(entry);
58 if (index >= 0) {
59 mKeyMementos.erase(mKeyMementos.begin() + index);
60 return true;
61 }
62 /* FIXME: We can't just drop the key up event because that prevents creating
63 * popup windows that are automatically shown when a key is held and then
64 * dismissed when the key is released. The problem is that the popup will
65 * not have received the original key down, so the key up will be considered
66 * to be inconsistent with its observed state. We could perhaps handle this
67 * by synthesizing a key down but that will cause other problems.
68 *
69 * So for now, allow inconsistent key up events to be dispatched.
70 *
71 #if DEBUG_OUTBOUND_EVENT_DETAILS
72 ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
73 "keyCode=%d, scanCode=%d",
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070074 entry.deviceId, entry.source, entry.keyCode, entry.scanCode);
Garfield Tane84e6f92019-08-29 17:28:41 -070075 #endif
76 return false;
77 */
78 return true;
79 }
80
81 case AKEY_EVENT_ACTION_DOWN: {
82 ssize_t index = findKeyMemento(entry);
83 if (index >= 0) {
84 mKeyMementos.erase(mKeyMementos.begin() + index);
85 }
86 addKeyMemento(entry, flags);
87 return true;
88 }
89
90 default:
91 return true;
92 }
93}
94
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070095bool InputState::trackMotion(const MotionEntry& entry, int32_t action, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -070096 int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
97 switch (actionMasked) {
98 case AMOTION_EVENT_ACTION_UP:
99 case AMOTION_EVENT_ACTION_CANCEL: {
100 ssize_t index = findMotionMemento(entry, false /*hovering*/);
101 if (index >= 0) {
102 mMotionMementos.erase(mMotionMementos.begin() + index);
103 return true;
104 }
Arthur Hung1a1007b2022-05-11 07:15:01 +0000105 if (DEBUG_OUTBOUND_EVENT_DETAILS) {
106 ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
107 "displayId=%" PRId32 ", actionMasked=%d",
108 entry.deviceId, entry.source, entry.displayId, actionMasked);
109 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700110 return false;
111 }
112
113 case AMOTION_EVENT_ACTION_DOWN: {
114 ssize_t index = findMotionMemento(entry, false /*hovering*/);
115 if (index >= 0) {
116 mMotionMementos.erase(mMotionMementos.begin() + index);
117 }
118 addMotionMemento(entry, flags, false /*hovering*/);
119 return true;
120 }
121
122 case AMOTION_EVENT_ACTION_POINTER_UP:
123 case AMOTION_EVENT_ACTION_POINTER_DOWN:
124 case AMOTION_EVENT_ACTION_MOVE: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700125 if (entry.source & AINPUT_SOURCE_CLASS_NAVIGATION) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700126 // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need
127 // to generate cancellation events for these since they're based in relative rather
128 // than absolute units.
129 return true;
130 }
131
132 ssize_t index = findMotionMemento(entry, false /*hovering*/);
133
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700134 if (entry.source & AINPUT_SOURCE_CLASS_JOYSTICK) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700135 // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
136 // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral.
137 // Any other value and we need to track the motion so we can send cancellation
138 // events for anything generating fallback events (e.g. DPad keys for joystick
139 // movements).
140 if (index >= 0) {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700141 if (entry.pointerCoords[0].isEmpty()) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700142 mMotionMementos.erase(mMotionMementos.begin() + index);
143 } else {
144 MotionMemento& memento = mMotionMementos[index];
145 memento.setPointers(entry);
146 }
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700147 } else if (!entry.pointerCoords[0].isEmpty()) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700148 addMotionMemento(entry, flags, false /*hovering*/);
149 }
150
151 // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
152 return true;
153 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800154
Garfield Tane84e6f92019-08-29 17:28:41 -0700155 if (index >= 0) {
156 MotionMemento& memento = mMotionMementos[index];
Svet Ganov5d3bc372020-01-26 23:11:07 -0800157 if (memento.firstNewPointerIdx < 0) {
158 memento.setPointers(entry);
159 return true;
160 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700161 }
Arthur Hung1a1007b2022-05-11 07:15:01 +0000162 if (DEBUG_OUTBOUND_EVENT_DETAILS) {
163 ALOGD("Dropping inconsistent motion pointer up/down or move event: "
164 "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
165 entry.deviceId, entry.source, entry.displayId, actionMasked);
166 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700167 return false;
168 }
169
170 case AMOTION_EVENT_ACTION_HOVER_EXIT: {
171 ssize_t index = findMotionMemento(entry, true /*hovering*/);
172 if (index >= 0) {
173 mMotionMementos.erase(mMotionMementos.begin() + index);
174 return true;
175 }
Arthur Hung1a1007b2022-05-11 07:15:01 +0000176 if (DEBUG_OUTBOUND_EVENT_DETAILS) {
177 ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
178 "displayId=%" PRId32,
179 entry.deviceId, entry.source, entry.displayId);
180 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700181 return false;
182 }
183
184 case AMOTION_EVENT_ACTION_HOVER_ENTER:
185 case AMOTION_EVENT_ACTION_HOVER_MOVE: {
186 ssize_t index = findMotionMemento(entry, true /*hovering*/);
187 if (index >= 0) {
188 mMotionMementos.erase(mMotionMementos.begin() + index);
189 }
190 addMotionMemento(entry, flags, true /*hovering*/);
191 return true;
192 }
193
194 default:
195 return true;
196 }
197}
198
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700199ssize_t InputState::findKeyMemento(const KeyEntry& entry) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700200 for (size_t i = 0; i < mKeyMementos.size(); i++) {
201 const KeyMemento& memento = mKeyMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700202 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
203 memento.displayId == entry.displayId && memento.keyCode == entry.keyCode &&
204 memento.scanCode == entry.scanCode) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700205 return i;
206 }
207 }
208 return -1;
209}
210
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700211ssize_t InputState::findMotionMemento(const MotionEntry& entry, bool hovering) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700212 for (size_t i = 0; i < mMotionMementos.size(); i++) {
213 const MotionMemento& memento = mMotionMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700214 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
215 memento.displayId == entry.displayId && memento.hovering == hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700216 return i;
217 }
218 }
219 return -1;
220}
221
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700222void InputState::addKeyMemento(const KeyEntry& entry, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700223 KeyMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700224 memento.deviceId = entry.deviceId;
225 memento.source = entry.source;
226 memento.displayId = entry.displayId;
227 memento.keyCode = entry.keyCode;
228 memento.scanCode = entry.scanCode;
229 memento.metaState = entry.metaState;
Garfield Tane84e6f92019-08-29 17:28:41 -0700230 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700231 memento.downTime = entry.downTime;
232 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700233 mKeyMementos.push_back(memento);
234}
235
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700236void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700237 MotionMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700238 memento.deviceId = entry.deviceId;
239 memento.source = entry.source;
240 memento.displayId = entry.displayId;
Garfield Tane84e6f92019-08-29 17:28:41 -0700241 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700242 memento.xPrecision = entry.xPrecision;
243 memento.yPrecision = entry.yPrecision;
244 memento.xCursorPosition = entry.xCursorPosition;
245 memento.yCursorPosition = entry.yCursorPosition;
246 memento.downTime = entry.downTime;
Garfield Tane84e6f92019-08-29 17:28:41 -0700247 memento.setPointers(entry);
248 memento.hovering = hovering;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700249 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700250 mMotionMementos.push_back(memento);
251}
252
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700253void InputState::MotionMemento::setPointers(const MotionEntry& entry) {
254 pointerCount = entry.pointerCount;
255 for (uint32_t i = 0; i < entry.pointerCount; i++) {
256 pointerProperties[i].copyFrom(entry.pointerProperties[i]);
257 pointerCoords[i].copyFrom(entry.pointerCoords[i]);
Garfield Tane84e6f92019-08-29 17:28:41 -0700258 }
259}
260
Svet Ganov5d3bc372020-01-26 23:11:07 -0800261void InputState::MotionMemento::mergePointerStateTo(MotionMemento& other) const {
262 for (uint32_t i = 0; i < pointerCount; i++) {
263 if (other.firstNewPointerIdx < 0) {
264 other.firstNewPointerIdx = other.pointerCount;
265 }
266 other.pointerProperties[other.pointerCount].copyFrom(pointerProperties[i]);
267 other.pointerCoords[other.pointerCount].copyFrom(pointerCoords[i]);
268 other.pointerCount++;
269 }
270}
271
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700272std::vector<std::unique_ptr<EventEntry>> InputState::synthesizeCancelationEvents(
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700273 nsecs_t currentTime, const CancelationOptions& options) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700274 std::vector<std::unique_ptr<EventEntry>> events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700275 for (KeyMemento& memento : mKeyMementos) {
276 if (shouldCancelKey(memento, options)) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700277 events.push_back(
278 std::make_unique<KeyEntry>(mIdGenerator.nextId(), currentTime, memento.deviceId,
279 memento.source, memento.displayId,
280 memento.policyFlags, AKEY_EVENT_ACTION_UP,
281 memento.flags | AKEY_EVENT_FLAG_CANCELED,
282 memento.keyCode, memento.scanCode, memento.metaState,
283 0 /*repeatCount*/, memento.downTime));
Garfield Tane84e6f92019-08-29 17:28:41 -0700284 }
285 }
286
287 for (const MotionMemento& memento : mMotionMementos) {
288 if (shouldCancelMotion(memento, options)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000289 if (options.pointerIds == std::nullopt) {
290 const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
291 : AMOTION_EVENT_ACTION_CANCEL;
292 events.push_back(
293 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
294 memento.deviceId, memento.source,
295 memento.displayId, memento.policyFlags,
296 action, 0 /*actionButton*/, memento.flags,
297 AMETA_NONE, 0 /*buttonState*/,
298 MotionClassification::NONE,
299 AMOTION_EVENT_EDGE_FLAG_NONE,
300 memento.xPrecision, memento.yPrecision,
301 memento.xCursorPosition,
302 memento.yCursorPosition, memento.downTime,
303 memento.pointerCount,
304 memento.pointerProperties,
305 memento.pointerCoords));
306 } else {
307 std::vector<std::unique_ptr<MotionEntry>> pointerCancelEvents =
308 synthesizeCancelationEventsForPointers(memento, options.pointerIds.value(),
309 currentTime);
310 events.insert(events.end(), std::make_move_iterator(pointerCancelEvents.begin()),
311 std::make_move_iterator(pointerCancelEvents.end()));
312 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700313 }
314 }
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700315 return events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700316}
317
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700318std::vector<std::unique_ptr<EventEntry>> InputState::synthesizePointerDownEvents(
319 nsecs_t currentTime) {
320 std::vector<std::unique_ptr<EventEntry>> events;
Svet Ganov5d3bc372020-01-26 23:11:07 -0800321 for (MotionMemento& memento : mMotionMementos) {
322 if (!(memento.source & AINPUT_SOURCE_CLASS_POINTER)) {
323 continue;
324 }
325
326 if (memento.firstNewPointerIdx < 0) {
327 continue;
328 }
329
330 uint32_t pointerCount = 0;
331 PointerProperties pointerProperties[MAX_POINTERS];
332 PointerCoords pointerCoords[MAX_POINTERS];
333
334 // We will deliver all pointers the target already knows about
335 for (uint32_t i = 0; i < static_cast<uint32_t>(memento.firstNewPointerIdx); i++) {
336 pointerProperties[i].copyFrom(memento.pointerProperties[i]);
337 pointerCoords[i].copyFrom(memento.pointerCoords[i]);
338 pointerCount++;
339 }
340
341 // We will send explicit events for all pointers the target doesn't know about
342 for (uint32_t i = static_cast<uint32_t>(memento.firstNewPointerIdx);
343 i < memento.pointerCount; i++) {
344
345 pointerProperties[i].copyFrom(memento.pointerProperties[i]);
346 pointerCoords[i].copyFrom(memento.pointerCoords[i]);
347 pointerCount++;
348
349 // Down only if the first pointer, pointer down otherwise
350 const int32_t action = (pointerCount <= 1)
351 ? AMOTION_EVENT_ACTION_DOWN
352 : AMOTION_EVENT_ACTION_POINTER_DOWN
353 | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
354
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700355 events.push_back(
356 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
357 memento.deviceId, memento.source,
358 memento.displayId, memento.policyFlags, action,
359 0 /*actionButton*/, memento.flags, AMETA_NONE,
360 0 /*buttonState*/, MotionClassification::NONE,
361 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
362 memento.yPrecision, memento.xCursorPosition,
363 memento.yCursorPosition, memento.downTime,
Prabir Pradhan5beda762021-12-10 09:30:08 +0000364 pointerCount, pointerProperties, pointerCoords));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800365 }
366
367 memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
368 }
369
370 return events;
371}
372
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000373std::vector<std::unique_ptr<MotionEntry>> InputState::synthesizeCancelationEventsForPointers(
374 const MotionMemento& memento, const BitSet32 pointerIds, nsecs_t currentTime) {
375 std::vector<std::unique_ptr<MotionEntry>> events;
376 std::vector<uint32_t> canceledPointerIndices;
377 std::vector<PointerProperties> pointerProperties(MAX_POINTERS);
378 std::vector<PointerCoords> pointerCoords(MAX_POINTERS);
379 for (uint32_t pointerIdx = 0; pointerIdx < memento.pointerCount; pointerIdx++) {
380 uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
381 pointerProperties[pointerIdx].copyFrom(memento.pointerProperties[pointerIdx]);
382 pointerCoords[pointerIdx].copyFrom(memento.pointerCoords[pointerIdx]);
383 if (pointerIds.hasBit(pointerId)) {
384 canceledPointerIndices.push_back(pointerIdx);
385 }
386 }
387
388 if (canceledPointerIndices.size() == memento.pointerCount) {
389 const int32_t action =
390 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
391 events.push_back(
392 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime, memento.deviceId,
393 memento.source, memento.displayId,
394 memento.policyFlags, action, 0 /*actionButton*/,
395 memento.flags, AMETA_NONE, 0 /*buttonState*/,
396 MotionClassification::NONE,
397 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
398 memento.yPrecision, memento.xCursorPosition,
399 memento.yCursorPosition, memento.downTime,
400 memento.pointerCount, memento.pointerProperties,
401 memento.pointerCoords));
402 } else {
403 // If we aren't canceling all pointers, we need to generated ACTION_POINTER_UP with
404 // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
405 // previously canceled pointers from PointerProperties and PointerCoords, and update
406 // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
407 // can just slide the remaining pointers to the beginning of the array when a pointer is
408 // canceled.
409 std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
410 std::greater<uint32_t>());
411
412 uint32_t pointerCount = memento.pointerCount;
413 for (const uint32_t pointerIdx : canceledPointerIndices) {
414 const int32_t action = pointerCount == 1 ? AMOTION_EVENT_ACTION_CANCEL
415 : AMOTION_EVENT_ACTION_POINTER_UP |
416 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
417 events.push_back(
418 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
419 memento.deviceId, memento.source,
420 memento.displayId, memento.policyFlags, action,
421 0 /*actionButton*/,
422 memento.flags | AMOTION_EVENT_FLAG_CANCELED,
423 AMETA_NONE, 0 /*buttonState*/,
424 MotionClassification::NONE,
425 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
426 memento.yPrecision, memento.xCursorPosition,
427 memento.yCursorPosition, memento.downTime,
428 pointerCount, pointerProperties.data(),
429 pointerCoords.data()));
430
431 // Cleanup pointer information
432 pointerProperties.erase(pointerProperties.begin() + pointerIdx);
433 pointerCoords.erase(pointerCoords.begin() + pointerIdx);
434 pointerCount--;
435 }
436 }
437 return events;
438}
439
Garfield Tane84e6f92019-08-29 17:28:41 -0700440void InputState::clear() {
441 mKeyMementos.clear();
442 mMotionMementos.clear();
443 mFallbackKeys.clear();
444}
445
Svet Ganov5d3bc372020-01-26 23:11:07 -0800446void InputState::mergePointerStateTo(InputState& other) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700447 for (size_t i = 0; i < mMotionMementos.size(); i++) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800448 MotionMemento& memento = mMotionMementos[i];
449 // Since we support split pointers we need to merge touch events
450 // from the same source + device + screen.
Garfield Tane84e6f92019-08-29 17:28:41 -0700451 if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800452 bool merged = false;
453 for (size_t j = 0; j < other.mMotionMementos.size(); j++) {
454 MotionMemento& otherMemento = other.mMotionMementos[j];
Garfield Tane84e6f92019-08-29 17:28:41 -0700455 if (memento.deviceId == otherMemento.deviceId &&
456 memento.source == otherMemento.source &&
457 memento.displayId == otherMemento.displayId) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800458 memento.mergePointerStateTo(otherMemento);
459 merged = true;
460 break;
Garfield Tane84e6f92019-08-29 17:28:41 -0700461 }
462 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800463 if (!merged) {
464 memento.firstNewPointerIdx = 0;
465 other.mMotionMementos.push_back(memento);
466 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700467 }
468 }
469}
470
471int32_t InputState::getFallbackKey(int32_t originalKeyCode) {
472 ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
473 return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
474}
475
476void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
477 ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
478 if (index >= 0) {
479 mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
480 } else {
481 mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
482 }
483}
484
485void InputState::removeFallbackKey(int32_t originalKeyCode) {
486 mFallbackKeys.removeItem(originalKeyCode);
487}
488
489bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
490 if (options.keyCode && memento.keyCode != options.keyCode.value()) {
491 return false;
492 }
493
494 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
495 return false;
496 }
497
498 if (options.displayId && memento.displayId != options.displayId.value()) {
499 return false;
500 }
501
502 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000503 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
504 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700505 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000506 case CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700507 return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
508 default:
509 return false;
510 }
511}
512
513bool InputState::shouldCancelMotion(const MotionMemento& memento,
514 const CancelationOptions& options) {
515 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
516 return false;
517 }
518
519 if (options.displayId && memento.displayId != options.displayId.value()) {
520 return false;
521 }
522
523 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000524 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700525 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000526 case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700527 return memento.source & AINPUT_SOURCE_CLASS_POINTER;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000528 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700529 return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
530 default:
531 return false;
532 }
533}
534
535} // namespace android::inputdispatcher