blob: 94f38131b628bf1f138f144055eea7377791cb21 [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
Garfield Tane84e6f92019-08-29 17:28:41 -070031bool InputState::isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const {
32 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
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070041bool InputState::trackKey(const KeyEntry& entry, int32_t action, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -070042 switch (action) {
43 case AKEY_EVENT_ACTION_UP: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070044 if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
Garfield Tane84e6f92019-08-29 17:28:41 -070045 for (size_t i = 0; i < mFallbackKeys.size();) {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070046 if (mFallbackKeys.valueAt(i) == entry.keyCode) {
Garfield Tane84e6f92019-08-29 17:28:41 -070047 mFallbackKeys.removeItemsAt(i);
48 } else {
49 i += 1;
50 }
51 }
52 }
53 ssize_t index = findKeyMemento(entry);
54 if (index >= 0) {
55 mKeyMementos.erase(mKeyMementos.begin() + index);
56 return true;
57 }
58 /* FIXME: We can't just drop the key up event because that prevents creating
59 * popup windows that are automatically shown when a key is held and then
60 * dismissed when the key is released. The problem is that the popup will
61 * not have received the original key down, so the key up will be considered
62 * to be inconsistent with its observed state. We could perhaps handle this
63 * by synthesizing a key down but that will cause other problems.
64 *
65 * So for now, allow inconsistent key up events to be dispatched.
66 *
67 #if DEBUG_OUTBOUND_EVENT_DETAILS
68 ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
69 "keyCode=%d, scanCode=%d",
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070070 entry.deviceId, entry.source, entry.keyCode, entry.scanCode);
Garfield Tane84e6f92019-08-29 17:28:41 -070071 #endif
72 return false;
73 */
74 return true;
75 }
76
77 case AKEY_EVENT_ACTION_DOWN: {
78 ssize_t index = findKeyMemento(entry);
79 if (index >= 0) {
80 mKeyMementos.erase(mKeyMementos.begin() + index);
81 }
82 addKeyMemento(entry, flags);
83 return true;
84 }
85
86 default:
87 return true;
88 }
89}
90
Siarhei Vishniakoud2770042019-10-29 11:08:14 -070091bool InputState::trackMotion(const MotionEntry& entry, int32_t action, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -070092 int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
93 switch (actionMasked) {
94 case AMOTION_EVENT_ACTION_UP:
95 case AMOTION_EVENT_ACTION_CANCEL: {
Harry Cutts33476232023-01-30 19:57:29 +000096 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -070097 if (index >= 0) {
98 mMotionMementos.erase(mMotionMementos.begin() + index);
99 return true;
100 }
Arthur Hung1a1007b2022-05-11 07:15:01 +0000101 if (DEBUG_OUTBOUND_EVENT_DETAILS) {
102 ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
103 "displayId=%" PRId32 ", actionMasked=%d",
104 entry.deviceId, entry.source, entry.displayId, actionMasked);
105 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700106 return false;
107 }
108
109 case AMOTION_EVENT_ACTION_DOWN: {
Harry Cutts33476232023-01-30 19:57:29 +0000110 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700111 if (index >= 0) {
112 mMotionMementos.erase(mMotionMementos.begin() + index);
113 }
Harry Cutts33476232023-01-30 19:57:29 +0000114 addMotionMemento(entry, flags, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700115 return true;
116 }
117
118 case AMOTION_EVENT_ACTION_POINTER_UP:
119 case AMOTION_EVENT_ACTION_POINTER_DOWN:
120 case AMOTION_EVENT_ACTION_MOVE: {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700121 if (entry.source & AINPUT_SOURCE_CLASS_NAVIGATION) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700122 // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need
123 // to generate cancellation events for these since they're based in relative rather
124 // than absolute units.
125 return true;
126 }
127
Harry Cutts33476232023-01-30 19:57:29 +0000128 ssize_t index = findMotionMemento(entry, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700129
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700130 if (entry.source & AINPUT_SOURCE_CLASS_JOYSTICK) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700131 // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
132 // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral.
133 // Any other value and we need to track the motion so we can send cancellation
134 // events for anything generating fallback events (e.g. DPad keys for joystick
135 // movements).
136 if (index >= 0) {
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700137 if (entry.pointerCoords[0].isEmpty()) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700138 mMotionMementos.erase(mMotionMementos.begin() + index);
139 } else {
140 MotionMemento& memento = mMotionMementos[index];
141 memento.setPointers(entry);
142 }
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700143 } else if (!entry.pointerCoords[0].isEmpty()) {
Harry Cutts33476232023-01-30 19:57:29 +0000144 addMotionMemento(entry, flags, /*hovering=*/false);
Garfield Tane84e6f92019-08-29 17:28:41 -0700145 }
146
147 // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
148 return true;
149 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800150
Garfield Tane84e6f92019-08-29 17:28:41 -0700151 if (index >= 0) {
152 MotionMemento& memento = mMotionMementos[index];
Svet Ganov5d3bc372020-01-26 23:11:07 -0800153 if (memento.firstNewPointerIdx < 0) {
154 memento.setPointers(entry);
155 return true;
156 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700157 }
Arthur Hung1a1007b2022-05-11 07:15:01 +0000158 if (DEBUG_OUTBOUND_EVENT_DETAILS) {
159 ALOGD("Dropping inconsistent motion pointer up/down or move event: "
160 "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
161 entry.deviceId, entry.source, entry.displayId, actionMasked);
162 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700163 return false;
164 }
165
166 case AMOTION_EVENT_ACTION_HOVER_EXIT: {
Harry Cutts33476232023-01-30 19:57:29 +0000167 ssize_t index = findMotionMemento(entry, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700168 if (index >= 0) {
169 mMotionMementos.erase(mMotionMementos.begin() + index);
170 return true;
171 }
Arthur Hung1a1007b2022-05-11 07:15:01 +0000172 if (DEBUG_OUTBOUND_EVENT_DETAILS) {
173 ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
174 "displayId=%" PRId32,
175 entry.deviceId, entry.source, entry.displayId);
176 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700177 return false;
178 }
179
180 case AMOTION_EVENT_ACTION_HOVER_ENTER:
181 case AMOTION_EVENT_ACTION_HOVER_MOVE: {
Harry Cutts33476232023-01-30 19:57:29 +0000182 ssize_t index = findMotionMemento(entry, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700183 if (index >= 0) {
184 mMotionMementos.erase(mMotionMementos.begin() + index);
185 }
Harry Cutts33476232023-01-30 19:57:29 +0000186 addMotionMemento(entry, flags, /*hovering=*/true);
Garfield Tane84e6f92019-08-29 17:28:41 -0700187 return true;
188 }
189
190 default:
191 return true;
192 }
193}
194
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700195ssize_t InputState::findKeyMemento(const KeyEntry& entry) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700196 for (size_t i = 0; i < mKeyMementos.size(); i++) {
197 const KeyMemento& memento = mKeyMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700198 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
199 memento.displayId == entry.displayId && memento.keyCode == entry.keyCode &&
200 memento.scanCode == entry.scanCode) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700201 return i;
202 }
203 }
204 return -1;
205}
206
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700207ssize_t InputState::findMotionMemento(const MotionEntry& entry, bool hovering) const {
Garfield Tane84e6f92019-08-29 17:28:41 -0700208 for (size_t i = 0; i < mMotionMementos.size(); i++) {
209 const MotionMemento& memento = mMotionMementos[i];
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700210 if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
211 memento.displayId == entry.displayId && memento.hovering == hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700212 return i;
213 }
214 }
215 return -1;
216}
217
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700218void InputState::addKeyMemento(const KeyEntry& entry, int32_t flags) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700219 KeyMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700220 memento.deviceId = entry.deviceId;
221 memento.source = entry.source;
222 memento.displayId = entry.displayId;
223 memento.keyCode = entry.keyCode;
224 memento.scanCode = entry.scanCode;
225 memento.metaState = entry.metaState;
Garfield Tane84e6f92019-08-29 17:28:41 -0700226 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700227 memento.downTime = entry.downTime;
228 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700229 mKeyMementos.push_back(memento);
230}
231
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700232void InputState::addMotionMemento(const MotionEntry& entry, int32_t flags, bool hovering) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700233 MotionMemento memento;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700234 memento.deviceId = entry.deviceId;
235 memento.source = entry.source;
236 memento.displayId = entry.displayId;
Garfield Tane84e6f92019-08-29 17:28:41 -0700237 memento.flags = flags;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700238 memento.xPrecision = entry.xPrecision;
239 memento.yPrecision = entry.yPrecision;
240 memento.xCursorPosition = entry.xCursorPosition;
241 memento.yCursorPosition = entry.yCursorPosition;
242 memento.downTime = entry.downTime;
Garfield Tane84e6f92019-08-29 17:28:41 -0700243 memento.setPointers(entry);
244 memento.hovering = hovering;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700245 memento.policyFlags = entry.policyFlags;
Garfield Tane84e6f92019-08-29 17:28:41 -0700246 mMotionMementos.push_back(memento);
247}
248
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700249void InputState::MotionMemento::setPointers(const MotionEntry& entry) {
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800250 pointerCount = 0;
Siarhei Vishniakoud2770042019-10-29 11:08:14 -0700251 for (uint32_t i = 0; i < entry.pointerCount; i++) {
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800252 if (MotionEvent::getActionMasked(entry.action) == AMOTION_EVENT_ACTION_POINTER_UP) {
253 // In POINTER_UP events, the pointer is leaving. Since the action is not stored,
254 // this departing pointer should not be recorded.
255 const uint8_t actionIndex = MotionEvent::getActionIndex(entry.action);
256 if (i == actionIndex) {
257 continue;
258 }
259 }
260 pointerProperties[pointerCount].copyFrom(entry.pointerProperties[i]);
261 pointerCoords[pointerCount].copyFrom(entry.pointerCoords[i]);
262 pointerCount++;
Garfield Tane84e6f92019-08-29 17:28:41 -0700263 }
264}
265
Svet Ganov5d3bc372020-01-26 23:11:07 -0800266void InputState::MotionMemento::mergePointerStateTo(MotionMemento& other) const {
267 for (uint32_t i = 0; i < pointerCount; i++) {
268 if (other.firstNewPointerIdx < 0) {
269 other.firstNewPointerIdx = other.pointerCount;
270 }
271 other.pointerProperties[other.pointerCount].copyFrom(pointerProperties[i]);
272 other.pointerCoords[other.pointerCount].copyFrom(pointerCoords[i]);
273 other.pointerCount++;
274 }
275}
276
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700277std::vector<std::unique_ptr<EventEntry>> InputState::synthesizeCancelationEvents(
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700278 nsecs_t currentTime, const CancelationOptions& options) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700279 std::vector<std::unique_ptr<EventEntry>> events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700280 for (KeyMemento& memento : mKeyMementos) {
281 if (shouldCancelKey(memento, options)) {
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700282 events.push_back(
283 std::make_unique<KeyEntry>(mIdGenerator.nextId(), currentTime, memento.deviceId,
284 memento.source, memento.displayId,
285 memento.policyFlags, AKEY_EVENT_ACTION_UP,
286 memento.flags | AKEY_EVENT_FLAG_CANCELED,
287 memento.keyCode, memento.scanCode, memento.metaState,
Harry Cutts33476232023-01-30 19:57:29 +0000288 /*repeatCount=*/0, memento.downTime));
Garfield Tane84e6f92019-08-29 17:28:41 -0700289 }
290 }
291
292 for (const MotionMemento& memento : mMotionMementos) {
293 if (shouldCancelMotion(memento, options)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000294 if (options.pointerIds == std::nullopt) {
295 const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
296 : AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800297 int32_t flags = memento.flags;
298 if (action == AMOTION_EVENT_ACTION_CANCEL) {
299 flags |= AMOTION_EVENT_FLAG_CANCELED;
300 }
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000301 events.push_back(
302 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
303 memento.deviceId, memento.source,
304 memento.displayId, memento.policyFlags,
Harry Cutts33476232023-01-30 19:57:29 +0000305 action, /*actionButton=*/0, flags, AMETA_NONE,
306 /*buttonState=*/0, MotionClassification::NONE,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000307 AMOTION_EVENT_EDGE_FLAG_NONE,
308 memento.xPrecision, memento.yPrecision,
309 memento.xCursorPosition,
310 memento.yCursorPosition, memento.downTime,
311 memento.pointerCount,
312 memento.pointerProperties,
313 memento.pointerCoords));
314 } else {
315 std::vector<std::unique_ptr<MotionEntry>> pointerCancelEvents =
316 synthesizeCancelationEventsForPointers(memento, options.pointerIds.value(),
317 currentTime);
318 events.insert(events.end(), std::make_move_iterator(pointerCancelEvents.begin()),
319 std::make_move_iterator(pointerCancelEvents.end()));
320 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700321 }
322 }
Siarhei Vishniakou00fca7c2019-10-29 13:05:57 -0700323 return events;
Garfield Tane84e6f92019-08-29 17:28:41 -0700324}
325
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700326std::vector<std::unique_ptr<EventEntry>> InputState::synthesizePointerDownEvents(
327 nsecs_t currentTime) {
328 std::vector<std::unique_ptr<EventEntry>> events;
Svet Ganov5d3bc372020-01-26 23:11:07 -0800329 for (MotionMemento& memento : mMotionMementos) {
330 if (!(memento.source & AINPUT_SOURCE_CLASS_POINTER)) {
331 continue;
332 }
333
334 if (memento.firstNewPointerIdx < 0) {
335 continue;
336 }
337
338 uint32_t pointerCount = 0;
339 PointerProperties pointerProperties[MAX_POINTERS];
340 PointerCoords pointerCoords[MAX_POINTERS];
341
342 // We will deliver all pointers the target already knows about
343 for (uint32_t i = 0; i < static_cast<uint32_t>(memento.firstNewPointerIdx); i++) {
344 pointerProperties[i].copyFrom(memento.pointerProperties[i]);
345 pointerCoords[i].copyFrom(memento.pointerCoords[i]);
346 pointerCount++;
347 }
348
349 // We will send explicit events for all pointers the target doesn't know about
350 for (uint32_t i = static_cast<uint32_t>(memento.firstNewPointerIdx);
351 i < memento.pointerCount; i++) {
352
353 pointerProperties[i].copyFrom(memento.pointerProperties[i]);
354 pointerCoords[i].copyFrom(memento.pointerCoords[i]);
355 pointerCount++;
356
357 // Down only if the first pointer, pointer down otherwise
358 const int32_t action = (pointerCount <= 1)
359 ? AMOTION_EVENT_ACTION_DOWN
360 : AMOTION_EVENT_ACTION_POINTER_DOWN
361 | (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
362
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700363 events.push_back(
364 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
365 memento.deviceId, memento.source,
366 memento.displayId, memento.policyFlags, action,
Harry Cutts33476232023-01-30 19:57:29 +0000367 /*actionButton=*/0, memento.flags, AMETA_NONE,
368 /*buttonState=*/0, MotionClassification::NONE,
Siarhei Vishniakoua9a7ee82019-10-14 16:28:19 -0700369 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
370 memento.yPrecision, memento.xCursorPosition,
371 memento.yCursorPosition, memento.downTime,
Prabir Pradhan5beda762021-12-10 09:30:08 +0000372 pointerCount, pointerProperties, pointerCoords));
Svet Ganov5d3bc372020-01-26 23:11:07 -0800373 }
374
375 memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
376 }
377
378 return events;
379}
380
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000381std::vector<std::unique_ptr<MotionEntry>> InputState::synthesizeCancelationEventsForPointers(
Siarhei Vishniakou8a878352023-01-30 14:05:01 -0800382 const MotionMemento& memento, std::bitset<MAX_POINTER_ID + 1> pointerIds,
383 nsecs_t currentTime) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000384 std::vector<std::unique_ptr<MotionEntry>> events;
385 std::vector<uint32_t> canceledPointerIndices;
386 std::vector<PointerProperties> pointerProperties(MAX_POINTERS);
387 std::vector<PointerCoords> pointerCoords(MAX_POINTERS);
388 for (uint32_t pointerIdx = 0; pointerIdx < memento.pointerCount; pointerIdx++) {
389 uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
390 pointerProperties[pointerIdx].copyFrom(memento.pointerProperties[pointerIdx]);
391 pointerCoords[pointerIdx].copyFrom(memento.pointerCoords[pointerIdx]);
Siarhei Vishniakou8a878352023-01-30 14:05:01 -0800392 if (pointerIds.test(pointerId)) {
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000393 canceledPointerIndices.push_back(pointerIdx);
394 }
395 }
396
397 if (canceledPointerIndices.size() == memento.pointerCount) {
398 const int32_t action =
399 memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800400 int32_t flags = memento.flags;
401 if (action == AMOTION_EVENT_ACTION_CANCEL) {
402 flags |= AMOTION_EVENT_FLAG_CANCELED;
403 }
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000404 events.push_back(
405 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime, memento.deviceId,
406 memento.source, memento.displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000407 memento.policyFlags, action, /*actionButton=*/0,
408 flags, AMETA_NONE, /*buttonState=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000409 MotionClassification::NONE,
410 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
411 memento.yPrecision, memento.xCursorPosition,
412 memento.yCursorPosition, memento.downTime,
413 memento.pointerCount, memento.pointerProperties,
414 memento.pointerCoords));
415 } else {
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -0800416 // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000417 // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
418 // previously canceled pointers from PointerProperties and PointerCoords, and update
419 // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
420 // can just slide the remaining pointers to the beginning of the array when a pointer is
421 // canceled.
422 std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
423 std::greater<uint32_t>());
424
425 uint32_t pointerCount = memento.pointerCount;
426 for (const uint32_t pointerIdx : canceledPointerIndices) {
427 const int32_t action = pointerCount == 1 ? AMOTION_EVENT_ACTION_CANCEL
428 : AMOTION_EVENT_ACTION_POINTER_UP |
429 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
430 events.push_back(
431 std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
432 memento.deviceId, memento.source,
433 memento.displayId, memento.policyFlags, action,
Harry Cutts33476232023-01-30 19:57:29 +0000434 /*actionButton=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000435 memento.flags | AMOTION_EVENT_FLAG_CANCELED,
Harry Cutts33476232023-01-30 19:57:29 +0000436 AMETA_NONE, /*buttonState=*/0,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +0000437 MotionClassification::NONE,
438 AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
439 memento.yPrecision, memento.xCursorPosition,
440 memento.yCursorPosition, memento.downTime,
441 pointerCount, pointerProperties.data(),
442 pointerCoords.data()));
443
444 // Cleanup pointer information
445 pointerProperties.erase(pointerProperties.begin() + pointerIdx);
446 pointerCoords.erase(pointerCoords.begin() + pointerIdx);
447 pointerCount--;
448 }
449 }
450 return events;
451}
452
Garfield Tane84e6f92019-08-29 17:28:41 -0700453void InputState::clear() {
454 mKeyMementos.clear();
455 mMotionMementos.clear();
456 mFallbackKeys.clear();
457}
458
Svet Ganov5d3bc372020-01-26 23:11:07 -0800459void InputState::mergePointerStateTo(InputState& other) {
Garfield Tane84e6f92019-08-29 17:28:41 -0700460 for (size_t i = 0; i < mMotionMementos.size(); i++) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800461 MotionMemento& memento = mMotionMementos[i];
462 // Since we support split pointers we need to merge touch events
463 // from the same source + device + screen.
Garfield Tane84e6f92019-08-29 17:28:41 -0700464 if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800465 bool merged = false;
466 for (size_t j = 0; j < other.mMotionMementos.size(); j++) {
467 MotionMemento& otherMemento = other.mMotionMementos[j];
Garfield Tane84e6f92019-08-29 17:28:41 -0700468 if (memento.deviceId == otherMemento.deviceId &&
469 memento.source == otherMemento.source &&
470 memento.displayId == otherMemento.displayId) {
Svet Ganov5d3bc372020-01-26 23:11:07 -0800471 memento.mergePointerStateTo(otherMemento);
472 merged = true;
473 break;
Garfield Tane84e6f92019-08-29 17:28:41 -0700474 }
475 }
Svet Ganov5d3bc372020-01-26 23:11:07 -0800476 if (!merged) {
477 memento.firstNewPointerIdx = 0;
478 other.mMotionMementos.push_back(memento);
479 }
Garfield Tane84e6f92019-08-29 17:28:41 -0700480 }
481 }
482}
483
484int32_t InputState::getFallbackKey(int32_t originalKeyCode) {
485 ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
486 return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
487}
488
489void InputState::setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode) {
490 ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
491 if (index >= 0) {
492 mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
493 } else {
494 mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
495 }
496}
497
498void InputState::removeFallbackKey(int32_t originalKeyCode) {
499 mFallbackKeys.removeItem(originalKeyCode);
500}
501
502bool InputState::shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options) {
503 if (options.keyCode && memento.keyCode != options.keyCode.value()) {
504 return false;
505 }
506
507 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
508 return false;
509 }
510
511 if (options.displayId && memento.displayId != options.displayId.value()) {
512 return false;
513 }
514
515 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000516 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
517 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700518 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000519 case CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700520 return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
521 default:
522 return false;
523 }
524}
525
526bool InputState::shouldCancelMotion(const MotionMemento& memento,
527 const CancelationOptions& options) {
528 if (options.deviceId && memento.deviceId != options.deviceId.value()) {
529 return false;
530 }
531
532 if (options.displayId && memento.displayId != options.displayId.value()) {
533 return false;
534 }
535
536 switch (options.mode) {
Michael Wrightfb04fd52022-11-24 22:31:11 +0000537 case CancelationOptions::Mode::CANCEL_ALL_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700538 return true;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000539 case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700540 return memento.source & AINPUT_SOURCE_CLASS_POINTER;
Michael Wrightfb04fd52022-11-24 22:31:11 +0000541 case CancelationOptions::Mode::CANCEL_NON_POINTER_EVENTS:
Garfield Tane84e6f92019-08-29 17:28:41 -0700542 return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
543 default:
544 return false;
545 }
546}
547
548} // namespace android::inputdispatcher