1 /*
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 
17 #include "DebugConfig.h"
18 #include "input/InputDevice.h"
19 
20 #include "InputState.h"
21 
22 #include <cinttypes>
23 #include "InputDispatcher.h"
24 
25 namespace android::inputdispatcher {
26 
InputState(const IdGenerator & idGenerator)27 InputState::InputState(const IdGenerator& idGenerator) : mIdGenerator(idGenerator) {}
28 
~InputState()29 InputState::~InputState() {}
30 
isHovering(DeviceId deviceId,uint32_t source,ui::LogicalDisplayId displayId) const31 bool InputState::isHovering(DeviceId deviceId, uint32_t source,
32                             ui::LogicalDisplayId displayId) const {
33     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 
trackKey(const KeyEntry & entry,int32_t flags)42 bool InputState::trackKey(const KeyEntry& entry, int32_t flags) {
43     switch (entry.action) {
44         case AKEY_EVENT_ACTION_UP: {
45             if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
46                 std::erase_if(mFallbackKeys,
47                               [&entry](const auto& item) { return item.second == entry.keyCode; });
48             }
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",
66                     entry.deviceId, entry.source, entry.keyCode, entry.scanCode);
67     #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 
87 /**
88  * Return:
89  *  true if the incoming event was correctly tracked,
90  *  false if the incoming event should be dropped.
91  */
trackMotion(const MotionEntry & entry,int32_t flags)92 bool InputState::trackMotion(const MotionEntry& entry, int32_t flags) {
93     // 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 
99     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             }
107         }
108     }
109 
110     int32_t actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
111     switch (actionMasked) {
112         case AMOTION_EVENT_ACTION_UP:
113         case AMOTION_EVENT_ACTION_CANCEL: {
114             ssize_t index = findMotionMemento(entry, /*hovering=*/false);
115             if (index >= 0) {
116                 mMotionMementos.erase(mMotionMementos.begin() + index);
117                 return true;
118             }
119 
120             return false;
121         }
122 
123         case AMOTION_EVENT_ACTION_DOWN: {
124             ssize_t index = findMotionMemento(entry, /*hovering=*/false);
125             if (index >= 0) {
126                 mMotionMementos.erase(mMotionMementos.begin() + index);
127             }
128             addMotionMemento(entry, flags, /*hovering=*/false);
129             return true;
130         }
131 
132         case AMOTION_EVENT_ACTION_POINTER_UP:
133         case AMOTION_EVENT_ACTION_POINTER_DOWN:
134         case AMOTION_EVENT_ACTION_MOVE: {
135             if (entry.source & AINPUT_SOURCE_CLASS_NAVIGATION) {
136                 // 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 
142             ssize_t index = findMotionMemento(entry, /*hovering=*/false);
143 
144             if (entry.source & AINPUT_SOURCE_CLASS_JOYSTICK) {
145                 // 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) {
151                     if (entry.pointerCoords[0].isEmpty()) {
152                         mMotionMementos.erase(mMotionMementos.begin() + index);
153                     } else {
154                         MotionMemento& memento = mMotionMementos[index];
155                         memento.setPointers(entry);
156                     }
157                 } else if (!entry.pointerCoords[0].isEmpty()) {
158                     addMotionMemento(entry, flags, /*hovering=*/false);
159                 }
160 
161                 // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
162                 return true;
163             }
164 
165             if (index >= 0) {
166                 MotionMemento& memento = mMotionMementos[index];
167                 if (memento.firstNewPointerIdx < 0) {
168                     memento.setPointers(entry);
169                     return true;
170                 }
171             }
172 
173             return false;
174         }
175 
176         case AMOTION_EVENT_ACTION_HOVER_EXIT: {
177             ssize_t index = findMotionMemento(entry, /*hovering=*/true);
178             if (index >= 0) {
179                 mMotionMementos.erase(mMotionMementos.begin() + index);
180                 return true;
181             }
182 
183             return false;
184         }
185 
186         case AMOTION_EVENT_ACTION_HOVER_ENTER:
187         case AMOTION_EVENT_ACTION_HOVER_MOVE: {
188             ssize_t index = findMotionMemento(entry, /*hovering=*/true);
189             if (index >= 0) {
190                 mMotionMementos.erase(mMotionMementos.begin() + index);
191             }
192             addMotionMemento(entry, flags, /*hovering=*/true);
193             return true;
194         }
195 
196         default:
197             return true;
198     }
199 }
200 
201 std::optional<std::pair<std::vector<PointerProperties>, std::vector<PointerCoords>>>
getPointersOfLastEvent(const MotionEntry & entry,bool hovering) const202 InputState::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 
findKeyMemento(const KeyEntry & entry) const211 ssize_t InputState::findKeyMemento(const KeyEntry& entry) const {
212     for (size_t i = 0; i < mKeyMementos.size(); i++) {
213         const KeyMemento& memento = mKeyMementos[i];
214         if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
215             memento.displayId == entry.displayId && memento.keyCode == entry.keyCode &&
216             memento.scanCode == entry.scanCode) {
217             return i;
218         }
219     }
220     return -1;
221 }
222 
findMotionMemento(const MotionEntry & entry,bool hovering) const223 ssize_t InputState::findMotionMemento(const MotionEntry& entry, bool hovering) const {
224     for (size_t i = 0; i < mMotionMementos.size(); i++) {
225         const MotionMemento& memento = mMotionMementos[i];
226         if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
227             memento.displayId == entry.displayId && memento.hovering == hovering) {
228             return i;
229         }
230     }
231     return -1;
232 }
233 
addKeyMemento(const KeyEntry & entry,int32_t flags)234 void InputState::addKeyMemento(const KeyEntry& entry, int32_t flags) {
235     KeyMemento memento;
236     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;
242     memento.flags = flags;
243     memento.downTime = entry.downTime;
244     memento.policyFlags = entry.policyFlags;
245     mKeyMementos.push_back(memento);
246 }
247 
addMotionMemento(const MotionEntry & entry,int32_t flags,bool hovering)248 void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool hovering) {
249     MotionMemento memento;
250     memento.deviceId = entry.deviceId;
251     memento.source = entry.source;
252     memento.displayId = entry.displayId;
253     memento.flags = flags;
254     memento.xPrecision = entry.xPrecision;
255     memento.yPrecision = entry.yPrecision;
256     memento.xCursorPosition = entry.xCursorPosition;
257     memento.yCursorPosition = entry.yCursorPosition;
258     memento.downTime = entry.downTime;
259     memento.setPointers(entry);
260     memento.hovering = hovering;
261     memento.policyFlags = entry.policyFlags;
262     mMotionMementos.push_back(memento);
263 }
264 
setPointers(const MotionEntry & entry)265 void InputState::MotionMemento::setPointers(const MotionEntry& entry) {
266     pointerProperties.clear();
267     pointerCoords.clear();
268 
269     for (uint32_t i = 0; i < entry.getPointerCount(); i++) {
270         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         }
278         pointerProperties.push_back(entry.pointerProperties[i]);
279         pointerCoords.push_back(entry.pointerCoords[i]);
280     }
281 }
282 
mergePointerStateTo(MotionMemento & other) const283 void InputState::MotionMemento::mergePointerStateTo(MotionMemento& other) const {
284     for (uint32_t i = 0; i < getPointerCount(); i++) {
285         if (other.firstNewPointerIdx < 0) {
286             other.firstNewPointerIdx = other.getPointerCount();
287         }
288         other.pointerProperties.push_back(pointerProperties[i]);
289         other.pointerCoords.push_back(pointerCoords[i]);
290     }
291 }
292 
getPointerCount() const293 size_t InputState::MotionMemento::getPointerCount() const {
294     return pointerProperties.size();
295 }
296 
shouldCancelPreviousStream(const MotionEntry & motionEntry) const297 bool InputState::shouldCancelPreviousStream(const MotionEntry& motionEntry) const {
298     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();
315     const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
316 
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 
327         // 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) {
342             LOG(INFO) << "Canceling stream: last displayId was " << lastMemento.displayId
343                       << " and new event is " << motionEntry;
344             return true;
345         }
346 
347         return false;
348     }
349 
350     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;
363         }
364 
365         // 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         }
370     }
371     // By default, don't cancel any events.
372     return false;
373 }
374 
cancelConflictingInputStream(const MotionEntry & motionEntry)375 std::unique_ptr<EventEntry> InputState::cancelConflictingInputStream(
376         const MotionEntry& motionEntry) {
377     if (!shouldCancelPreviousStream(motionEntry)) {
378         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 
387     if (!trackMotion(*cancelEntry, cancelEntry->flags)) {
388         LOG(FATAL) << "Generated inconsistent cancel event!";
389     }
390     return cancelEntry;
391 }
392 
createCancelEntryForMemento(const MotionMemento & memento,nsecs_t eventTime) const393 std::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     }
401     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,
405                                          /*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 
synthesizeCancelationEvents(nsecs_t currentTime,const CancelationOptions & options)412 std::vector<std::unique_ptr<EventEntry>> InputState::synthesizeCancelationEvents(
413         nsecs_t currentTime, const CancelationOptions& options) {
414     std::vector<std::unique_ptr<EventEntry>> events;
415     for (KeyMemento& memento : mKeyMementos) {
416         if (shouldCancelKey(memento, options)) {
417             events.push_back(
418                     std::make_unique<KeyEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
419                                                currentTime, memento.deviceId, memento.source,
420                                                memento.displayId, memento.policyFlags,
421                                                AKEY_EVENT_ACTION_UP,
422                                                memento.flags | AKEY_EVENT_FLAG_CANCELED,
423                                                memento.keyCode, memento.scanCode, memento.metaState,
424                                                /*repeatCount=*/0, memento.downTime));
425         }
426     }
427 
428     for (const MotionMemento& memento : mMotionMementos) {
429         if (shouldCancelMotion(memento, options)) {
430             if (options.pointerIds == std::nullopt) {
431                 events.push_back(createCancelEntryForMemento(memento, currentTime));
432             } 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             }
439         }
440     }
441     return events;
442 }
443 
synthesizePointerDownEvents(nsecs_t currentTime)444 std::vector<std::unique_ptr<EventEntry>> InputState::synthesizePointerDownEvents(
445         nsecs_t currentTime) {
446     std::vector<std::unique_ptr<EventEntry>> events;
447     for (MotionMemento& memento : mMotionMementos) {
448         if (!isFromSource(memento.source, AINPUT_SOURCE_CLASS_POINTER)) {
449             continue;
450         }
451 
452         if (memento.firstNewPointerIdx < 0) {
453             continue;
454         }
455 
456         std::vector<PointerProperties> pointerProperties;
457         std::vector<PointerCoords> pointerCoords;
458 
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++) {
461             pointerProperties.push_back(memento.pointerProperties[i]);
462             pointerCoords.push_back(memento.pointerCoords[i]);
463         }
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);
467              i < memento.getPointerCount(); i++) {
468             pointerProperties.push_back(memento.pointerProperties[i]);
469             pointerCoords.push_back(memento.pointerCoords[i]);
470 
471             const size_t pointerCount = pointerProperties.size();
472 
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 
479             events.push_back(
480                     std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
481                                                   currentTime, memento.deviceId, memento.source,
482                                                   memento.displayId, memento.policyFlags, action,
483                                                   /*actionButton=*/0, memento.flags, AMETA_NONE,
484                                                   /*buttonState=*/0, MotionClassification::NONE,
485                                                   AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
486                                                   memento.yPrecision, memento.xCursorPosition,
487                                                   memento.yCursorPosition, memento.downTime,
488                                                   pointerProperties, pointerCoords));
489         }
490 
491         memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
492     }
493 
494     return events;
495 }
496 
synthesizeCancelationEventsForPointers(const MotionMemento & memento,std::bitset<MAX_POINTER_ID+1> pointerIds,nsecs_t currentTime)497 std::vector<std::unique_ptr<MotionEntry>> InputState::synthesizeCancelationEventsForPointers(
498         const MotionMemento& memento, std::bitset<MAX_POINTER_ID + 1> pointerIds,
499         nsecs_t currentTime) {
500     std::vector<std::unique_ptr<MotionEntry>> events;
501     std::vector<uint32_t> canceledPointerIndices;
502 
503     for (uint32_t pointerIdx = 0; pointerIdx < memento.getPointerCount(); pointerIdx++) {
504         uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
505         if (pointerIds.test(pointerId)) {
506             canceledPointerIndices.push_back(pointerIdx);
507         }
508     }
509 
510     if (canceledPointerIndices.size() == memento.getPointerCount()) {
511         // We are cancelling all pointers.
512         events.emplace_back(createCancelEntryForMemento(memento, currentTime));
513         return events;
514     }
515 
516     // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
517     // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
518     // previously canceled pointers from PointerProperties and PointerCoords, and update
519     // pointerCount appropriately. For convenience, sort the canceled pointer indices in
520     // descending order so that we can just slide the remaining pointers to the beginning of
521     // the array when a pointer is canceled.
522     std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
523               std::greater<uint32_t>());
524 
525     std::vector<PointerProperties> pointerProperties = memento.pointerProperties;
526     std::vector<PointerCoords> pointerCoords = memento.pointerCoords;
527     for (const uint32_t pointerIdx : canceledPointerIndices) {
528         if (pointerProperties.size() <= 1) {
529             LOG(FATAL) << "Unexpected code path for canceling all pointers!";
530         }
531         const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
532                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
533         events.push_back(
534                 std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
535                                               currentTime, memento.deviceId, memento.source,
536                                               memento.displayId, memento.policyFlags, action,
537                                               /*actionButton=*/0,
538                                               memento.flags | AMOTION_EVENT_FLAG_CANCELED,
539                                               AMETA_NONE, /*buttonState=*/0,
540                                               MotionClassification::NONE,
541                                               AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
542                                               memento.yPrecision, memento.xCursorPosition,
543                                               memento.yCursorPosition, memento.downTime,
544                                               pointerProperties, pointerCoords));
545 
546         // Cleanup pointer information
547         pointerProperties.erase(pointerProperties.begin() + pointerIdx);
548         pointerCoords.erase(pointerCoords.begin() + pointerIdx);
549     }
550     return events;
551 }
552 
clear()553 void InputState::clear() {
554     mKeyMementos.clear();
555     mMotionMementos.clear();
556     mFallbackKeys.clear();
557 }
558 
mergePointerStateTo(InputState & other)559 void InputState::mergePointerStateTo(InputState& other) {
560     for (size_t i = 0; i < mMotionMementos.size(); i++) {
561         MotionMemento& memento = mMotionMementos[i];
562         // Since we support split pointers we need to merge touch events
563         // from the same source + device + screen.
564         if (isFromSource(memento.source, AINPUT_SOURCE_CLASS_POINTER)) {
565             bool merged = false;
566             for (size_t j = 0; j < other.mMotionMementos.size(); j++) {
567                 MotionMemento& otherMemento = other.mMotionMementos[j];
568                 if (memento.deviceId == otherMemento.deviceId &&
569                     memento.source == otherMemento.source &&
570                     memento.displayId == otherMemento.displayId) {
571                     memento.mergePointerStateTo(otherMemento);
572                     merged = true;
573                     break;
574                 }
575             }
576             if (!merged) {
577                 memento.firstNewPointerIdx = 0;
578                 other.mMotionMementos.push_back(memento);
579             }
580         }
581     }
582 }
583 
getFallbackKey(int32_t originalKeyCode)584 std::optional<int32_t> InputState::getFallbackKey(int32_t originalKeyCode) {
585     auto it = mFallbackKeys.find(originalKeyCode);
586     if (it == mFallbackKeys.end()) {
587         return {};
588     }
589     return it->second;
590 }
591 
setFallbackKey(int32_t originalKeyCode,int32_t fallbackKeyCode)592 void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
593     mFallbackKeys.insert_or_assign(originalKeyCode, fallbackKeyCode);
594 }
595 
removeFallbackKey(int32_t originalKeyCode)596 void InputState::removeFallbackKey(int32_t originalKeyCode) {
597     mFallbackKeys.erase(originalKeyCode);
598 }
599 
shouldCancelKey(const KeyMemento & memento,const CancelationOptions & options)600 bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
601     if (options.keyCode && memento.keyCode != options.keyCode.value()) {
602         return false;
603     }
604 
605     if (options.deviceId && memento.deviceId != options.deviceId.value()) {
606         return false;
607     }
608 
609     if (options.displayId && memento.displayId != options.displayId.value()) {
610         return false;
611     }
612 
613     switch (options.mode) {
614         case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
615         case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
616             return true;
617         case CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS:
618             return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
619         default:
620             return false;
621     }
622 }
623 
shouldCancelMotion(const MotionMemento & memento,const CancelationOptions & options)624 bool InputState::shouldCancelMotion(const MotionMemento& memento,
625                                     const CancelationOptions& options) {
626     if (options.deviceId && memento.deviceId != options.deviceId.value()) {
627         return false;
628     }
629 
630     if (options.displayId && memento.displayId != options.displayId.value()) {
631         return false;
632     }
633 
634     switch (options.mode) {
635         case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
636             return true;
637         case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
638             return memento.source & AINPUT_SOURCE_CLASS_POINTER;
639         case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
640             return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
641         default:
642             return false;
643     }
644 }
645 
operator <<(std::ostream & out,const InputState & state)646 std::ostream& operator<<(std::ostream& out, const InputState& state) {
647     if (!state.mMotionMementos.empty()) {
648         out << "mMotionMementos: ";
649         for (const InputState::MotionMemento& memento : state.mMotionMementos) {
650             out << "{deviceId= " << memento.deviceId << ", hovering=" << memento.hovering << "}, ";
651         }
652     }
653     return out;
654 }
655 
656 } // namespace android::inputdispatcher
657