blob: d59f274ab0e13dfc3e79f9ee5c0d9318306f8a0a [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 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#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
25#define DEBUG_HACKS 0
26
27// Log debug messages about virtual key processing.
28#define DEBUG_VIRTUAL_KEYS 0
29
30// Log debug messages about pointers.
31#define DEBUG_POINTERS 0
32
33// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
36// Log debug messages about gesture detection.
37#define DEBUG_GESTURES 0
38
39// Log debug messages about the vibrator.
40#define DEBUG_VIBRATOR 0
41
Michael Wright842500e2015-03-13 17:32:02 -070042// Log debug messages about fusing stylus data.
43#define DEBUG_STYLUS_FUSION 0
44
Michael Wrightd02c5b62014-02-10 15:10:22 -080045#include "InputReader.h"
46
Mark Salyzyna5e161b2016-09-29 08:08:05 -070047#include <errno.h>
Michael Wright842500e2015-03-13 17:32:02 -070048#include <inttypes.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070049#include <limits.h>
50#include <math.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080051#include <stddef.h>
52#include <stdlib.h>
53#include <unistd.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070054
Mark Salyzyn7823e122016-09-29 08:08:05 -070055#include <log/log.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070056
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080057#include <android-base/stringprintf.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070058#include <input/Keyboard.h>
59#include <input/VirtualKeyMap.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080060
61#define INDENT " "
62#define INDENT2 " "
63#define INDENT3 " "
64#define INDENT4 " "
65#define INDENT5 " "
66
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -080067using android::base::StringPrintf;
68
Michael Wrightd02c5b62014-02-10 15:10:22 -080069namespace android {
70
71// --- Constants ---
72
73// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
Siarhei Vishniakou9ffab0c2018-11-08 19:54:22 -080074static constexpr size_t MAX_SLOTS = 32;
Michael Wrightd02c5b62014-02-10 15:10:22 -080075
Michael Wright842500e2015-03-13 17:32:02 -070076// Maximum amount of latency to add to touch events while waiting for data from an
77// external stylus.
Siarhei Vishniakou9ffab0c2018-11-08 19:54:22 -080078static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
Michael Wright842500e2015-03-13 17:32:02 -070079
Michael Wright43fd19f2015-04-21 19:02:58 +010080// Maximum amount of time to wait on touch data before pushing out new pressure data.
Siarhei Vishniakou9ffab0c2018-11-08 19:54:22 -080081static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
Michael Wright43fd19f2015-04-21 19:02:58 +010082
83// Artificial latency on synthetic events created from stylus data without corresponding touch
84// data.
Siarhei Vishniakou9ffab0c2018-11-08 19:54:22 -080085static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
86
Michael Wrightd02c5b62014-02-10 15:10:22 -080087// --- Static Functions ---
88
89template<typename T>
90inline static T abs(const T& value) {
91 return value < 0 ? - value : value;
92}
93
94template<typename T>
95inline static T min(const T& a, const T& b) {
96 return a < b ? a : b;
97}
98
99template<typename T>
100inline static void swap(T& a, T& b) {
101 T temp = a;
102 a = b;
103 b = temp;
104}
105
106inline static float avg(float x, float y) {
107 return (x + y) / 2;
108}
109
110inline static float distance(float x1, float y1, float x2, float y2) {
111 return hypotf(x1 - x2, y1 - y2);
112}
113
114inline static int32_t signExtendNybble(int32_t value) {
115 return value >= 8 ? value - 16 : value;
116}
117
118static inline const char* toString(bool value) {
119 return value ? "true" : "false";
120}
121
122static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
123 const int32_t map[][4], size_t mapSize) {
124 if (orientation != DISPLAY_ORIENTATION_0) {
125 for (size_t i = 0; i < mapSize; i++) {
126 if (value == map[i][0]) {
127 return map[i][orientation];
128 }
129 }
130 }
131 return value;
132}
133
134static const int32_t keyCodeRotationMap[][4] = {
135 // key codes enumerated counter-clockwise with the original (unrotated) key first
136 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
137 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
138 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
139 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
140 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jim Millere7a57d12016-06-22 15:58:31 -0700141 { AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT,
142 AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT },
143 { AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP,
144 AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN },
145 { AKEYCODE_SYSTEM_NAVIGATION_UP, AKEYCODE_SYSTEM_NAVIGATION_LEFT,
146 AKEYCODE_SYSTEM_NAVIGATION_DOWN, AKEYCODE_SYSTEM_NAVIGATION_RIGHT },
147 { AKEYCODE_SYSTEM_NAVIGATION_LEFT, AKEYCODE_SYSTEM_NAVIGATION_DOWN,
148 AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP },
Michael Wrightd02c5b62014-02-10 15:10:22 -0800149};
150static const size_t keyCodeRotationMapSize =
151 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
152
Ivan Podogovb9afef32017-02-13 15:34:32 +0000153static int32_t rotateStemKey(int32_t value, int32_t orientation,
154 const int32_t map[][2], size_t mapSize) {
155 if (orientation == DISPLAY_ORIENTATION_180) {
156 for (size_t i = 0; i < mapSize; i++) {
157 if (value == map[i][0]) {
158 return map[i][1];
159 }
160 }
161 }
162 return value;
163}
164
165// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
166static int32_t stemKeyRotationMap[][2] = {
167 // key codes enumerated with the original (unrotated) key first
168 // no rotation, 180 degree rotation
169 { AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY },
170 { AKEYCODE_STEM_1, AKEYCODE_STEM_1 },
171 { AKEYCODE_STEM_2, AKEYCODE_STEM_2 },
172 { AKEYCODE_STEM_3, AKEYCODE_STEM_3 },
173};
174static const size_t stemKeyRotationMapSize =
175 sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
176
Michael Wrightd02c5b62014-02-10 15:10:22 -0800177static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Ivan Podogovb9afef32017-02-13 15:34:32 +0000178 keyCode = rotateStemKey(keyCode, orientation,
179 stemKeyRotationMap, stemKeyRotationMapSize);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180 return rotateValueUsingRotationMap(keyCode, orientation,
181 keyCodeRotationMap, keyCodeRotationMapSize);
182}
183
184static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
185 float temp;
186 switch (orientation) {
187 case DISPLAY_ORIENTATION_90:
188 temp = *deltaX;
189 *deltaX = *deltaY;
190 *deltaY = -temp;
191 break;
192
193 case DISPLAY_ORIENTATION_180:
194 *deltaX = -*deltaX;
195 *deltaY = -*deltaY;
196 break;
197
198 case DISPLAY_ORIENTATION_270:
199 temp = *deltaX;
200 *deltaX = -*deltaY;
201 *deltaY = temp;
202 break;
203 }
204}
205
206static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
207 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
208}
209
210// Returns true if the pointer should be reported as being down given the specified
211// button states. This determines whether the event is reported as a touch event.
212static bool isPointerDown(int32_t buttonState) {
213 return buttonState &
214 (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
215 | AMOTION_EVENT_BUTTON_TERTIARY);
216}
217
218static float calculateCommonVector(float a, float b) {
219 if (a > 0 && b > 0) {
220 return a < b ? a : b;
221 } else if (a < 0 && b < 0) {
222 return a > b ? a : b;
223 } else {
224 return 0;
225 }
226}
227
228static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100229 nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800230 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
231 int32_t buttonState, int32_t keyCode) {
232 if (
233 (action == AKEY_EVENT_ACTION_DOWN
234 && !(lastButtonState & buttonState)
235 && (currentButtonState & buttonState))
236 || (action == AKEY_EVENT_ACTION_UP
237 && (lastButtonState & buttonState)
238 && !(currentButtonState & buttonState))) {
Prabir Pradhan42611e02018-11-27 14:04:02 -0800239 NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
240 policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800241 context->getListener()->notifyKey(&args);
242 }
243}
244
245static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100246 nsecs_t when, int32_t deviceId, uint32_t source, int32_t displayId,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800247 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100248 synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249 lastButtonState, currentButtonState,
250 AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100251 synthesizeButtonKey(context, action, when, deviceId, source, displayId, policyFlags,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800252 lastButtonState, currentButtonState,
253 AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
254}
255
256
Michael Wrightd02c5b62014-02-10 15:10:22 -0800257// --- InputReader ---
258
Siarhei Vishniakou3bc7e092019-07-24 17:43:30 -0700259InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
260 const sp<InputReaderPolicyInterface>& policy,
261 const sp<InputListenerInterface>& listener)
262 : mContext(this),
263 mEventHub(eventHub),
264 mPolicy(policy),
265 mNextSequenceNum(1),
266 mGlobalMetaState(0),
267 mGeneration(1),
268 mDisableVirtualKeysTimeout(LLONG_MIN),
269 mNextTimeout(LLONG_MAX),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800270 mConfigurationChangesToRefresh(0) {
271 mQueuedListener = new QueuedInputListener(listener);
272
273 { // acquire lock
274 AutoMutex _l(mLock);
275
276 refreshConfigurationLocked(0);
277 updateGlobalMetaStateLocked();
278 } // release lock
279}
280
281InputReader::~InputReader() {
282 for (size_t i = 0; i < mDevices.size(); i++) {
283 delete mDevices.valueAt(i);
284 }
285}
286
287void InputReader::loopOnce() {
288 int32_t oldGeneration;
289 int32_t timeoutMillis;
290 bool inputDevicesChanged = false;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800291 std::vector<InputDeviceInfo> inputDevices;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800292 { // acquire lock
293 AutoMutex _l(mLock);
294
295 oldGeneration = mGeneration;
296 timeoutMillis = -1;
297
298 uint32_t changes = mConfigurationChangesToRefresh;
299 if (changes) {
300 mConfigurationChangesToRefresh = 0;
301 timeoutMillis = 0;
302 refreshConfigurationLocked(changes);
303 } else if (mNextTimeout != LLONG_MAX) {
304 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
305 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
306 }
307 } // release lock
308
309 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
310
311 { // acquire lock
312 AutoMutex _l(mLock);
313 mReaderIsAliveCondition.broadcast();
314
315 if (count) {
316 processEventsLocked(mEventBuffer, count);
317 }
318
319 if (mNextTimeout != LLONG_MAX) {
320 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
321 if (now >= mNextTimeout) {
322#if DEBUG_RAW_EVENTS
323 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
324#endif
325 mNextTimeout = LLONG_MAX;
326 timeoutExpiredLocked(now);
327 }
328 }
329
330 if (oldGeneration != mGeneration) {
331 inputDevicesChanged = true;
332 getInputDevicesLocked(inputDevices);
333 }
334 } // release lock
335
336 // Send out a message that the describes the changed input devices.
337 if (inputDevicesChanged) {
338 mPolicy->notifyInputDevicesChanged(inputDevices);
339 }
340
341 // Flush queued events out to the listener.
342 // This must happen outside of the lock because the listener could potentially call
343 // back into the InputReader's methods, such as getScanCodeState, or become blocked
344 // on another thread similarly waiting to acquire the InputReader lock thereby
345 // resulting in a deadlock. This situation is actually quite plausible because the
346 // listener is actually the input dispatcher, which calls into the window manager,
347 // which occasionally calls into the input reader.
348 mQueuedListener->flush();
349}
350
351void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
352 for (const RawEvent* rawEvent = rawEvents; count;) {
353 int32_t type = rawEvent->type;
354 size_t batchSize = 1;
355 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
356 int32_t deviceId = rawEvent->deviceId;
357 while (batchSize < count) {
358 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
359 || rawEvent[batchSize].deviceId != deviceId) {
360 break;
361 }
362 batchSize += 1;
363 }
364#if DEBUG_RAW_EVENTS
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -0700365 ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800366#endif
367 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
368 } else {
369 switch (rawEvent->type) {
370 case EventHubInterface::DEVICE_ADDED:
371 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
372 break;
373 case EventHubInterface::DEVICE_REMOVED:
374 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
375 break;
376 case EventHubInterface::FINISHED_DEVICE_SCAN:
377 handleConfigurationChangedLocked(rawEvent->when);
378 break;
379 default:
380 ALOG_ASSERT(false); // can't happen
381 break;
382 }
383 }
384 count -= batchSize;
385 rawEvent += batchSize;
386 }
387}
388
389void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
390 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
391 if (deviceIndex >= 0) {
392 ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
393 return;
394 }
395
396 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
397 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
398 int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
399
400 InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
401 device->configure(when, &mConfig, 0);
402 device->reset(when);
403
404 if (device->isIgnored()) {
405 ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100406 identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800407 } else {
408 ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100409 identifier.name.c_str(), device->getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800410 }
411
412 mDevices.add(deviceId, device);
413 bumpGenerationLocked();
Michael Wright842500e2015-03-13 17:32:02 -0700414
415 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
416 notifyExternalStylusPresenceChanged();
417 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800418}
419
420void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
Yi Kong9b14ac62018-07-17 13:48:38 -0700421 InputDevice* device = nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800422 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
423 if (deviceIndex < 0) {
424 ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
425 return;
426 }
427
428 device = mDevices.valueAt(deviceIndex);
429 mDevices.removeItemsAt(deviceIndex, 1);
430 bumpGenerationLocked();
431
432 if (device->isIgnored()) {
433 ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100434 device->getId(), device->getName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800435 } else {
436 ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100437 device->getId(), device->getName().c_str(), device->getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800438 }
439
Michael Wright842500e2015-03-13 17:32:02 -0700440 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
441 notifyExternalStylusPresenceChanged();
442 }
443
Michael Wrightd02c5b62014-02-10 15:10:22 -0800444 device->reset(when);
445 delete device;
446}
447
448InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
449 const InputDeviceIdentifier& identifier, uint32_t classes) {
450 InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
451 controllerNumber, identifier, classes);
452
453 // External devices.
454 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
455 device->setExternal(true);
456 }
457
Tim Kilbourn063ff532015-04-08 10:26:18 -0700458 // Devices with mics.
459 if (classes & INPUT_DEVICE_CLASS_MIC) {
460 device->setMic(true);
461 }
462
Michael Wrightd02c5b62014-02-10 15:10:22 -0800463 // Switch-like devices.
464 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
465 device->addMapper(new SwitchInputMapper(device));
466 }
467
Prashant Malani1941ff52015-08-11 18:29:28 -0700468 // Scroll wheel-like devices.
469 if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
470 device->addMapper(new RotaryEncoderInputMapper(device));
471 }
472
Michael Wrightd02c5b62014-02-10 15:10:22 -0800473 // Vibrator-like devices.
474 if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
475 device->addMapper(new VibratorInputMapper(device));
476 }
477
478 // Keyboard-like devices.
479 uint32_t keyboardSource = 0;
480 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
481 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
482 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
483 }
484 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
485 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
486 }
487 if (classes & INPUT_DEVICE_CLASS_DPAD) {
488 keyboardSource |= AINPUT_SOURCE_DPAD;
489 }
490 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
491 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
492 }
493
494 if (keyboardSource != 0) {
495 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
496 }
497
498 // Cursor-like devices.
499 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
500 device->addMapper(new CursorInputMapper(device));
501 }
502
503 // Touchscreens and touchpad devices.
504 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
505 device->addMapper(new MultiTouchInputMapper(device));
506 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
507 device->addMapper(new SingleTouchInputMapper(device));
508 }
509
510 // Joystick-like devices.
511 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
512 device->addMapper(new JoystickInputMapper(device));
513 }
514
Michael Wright842500e2015-03-13 17:32:02 -0700515 // External stylus-like devices.
516 if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
517 device->addMapper(new ExternalStylusInputMapper(device));
518 }
519
Michael Wrightd02c5b62014-02-10 15:10:22 -0800520 return device;
521}
522
523void InputReader::processEventsForDeviceLocked(int32_t deviceId,
524 const RawEvent* rawEvents, size_t count) {
525 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
526 if (deviceIndex < 0) {
527 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
528 return;
529 }
530
531 InputDevice* device = mDevices.valueAt(deviceIndex);
532 if (device->isIgnored()) {
533 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
534 return;
535 }
536
537 device->process(rawEvents, count);
538}
539
540void InputReader::timeoutExpiredLocked(nsecs_t when) {
541 for (size_t i = 0; i < mDevices.size(); i++) {
542 InputDevice* device = mDevices.valueAt(i);
543 if (!device->isIgnored()) {
544 device->timeoutExpired(when);
545 }
546 }
547}
548
549void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
550 // Reset global meta state because it depends on the list of all configured devices.
551 updateGlobalMetaStateLocked();
552
553 // Enqueue configuration changed.
Prabir Pradhan42611e02018-11-27 14:04:02 -0800554 NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800555 mQueuedListener->notifyConfigurationChanged(&args);
556}
557
558void InputReader::refreshConfigurationLocked(uint32_t changes) {
559 mPolicy->getReaderConfiguration(&mConfig);
560 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
561
562 if (changes) {
Siarhei Vishniakouc5ae0dc2019-07-10 15:51:18 -0700563 ALOGI("Reconfiguring input devices, changes=%s",
564 InputReaderConfiguration::changesToString(changes).c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800565 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
566
567 if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
568 mEventHub->requestReopenDevices();
569 } else {
570 for (size_t i = 0; i < mDevices.size(); i++) {
571 InputDevice* device = mDevices.valueAt(i);
572 device->configure(now, &mConfig, changes);
573 }
574 }
575 }
576}
577
578void InputReader::updateGlobalMetaStateLocked() {
579 mGlobalMetaState = 0;
580
581 for (size_t i = 0; i < mDevices.size(); i++) {
582 InputDevice* device = mDevices.valueAt(i);
583 mGlobalMetaState |= device->getMetaState();
584 }
585}
586
587int32_t InputReader::getGlobalMetaStateLocked() {
588 return mGlobalMetaState;
589}
590
Michael Wright842500e2015-03-13 17:32:02 -0700591void InputReader::notifyExternalStylusPresenceChanged() {
592 refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
593}
594
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800595void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
Michael Wright842500e2015-03-13 17:32:02 -0700596 for (size_t i = 0; i < mDevices.size(); i++) {
597 InputDevice* device = mDevices.valueAt(i);
598 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800599 InputDeviceInfo info;
600 device->getDeviceInfo(&info);
601 outDevices.push_back(info);
Michael Wright842500e2015-03-13 17:32:02 -0700602 }
603 }
604}
605
606void InputReader::dispatchExternalStylusState(const StylusState& state) {
607 for (size_t i = 0; i < mDevices.size(); i++) {
608 InputDevice* device = mDevices.valueAt(i);
609 device->updateExternalStylusState(state);
610 }
611}
612
Michael Wrightd02c5b62014-02-10 15:10:22 -0800613void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
614 mDisableVirtualKeysTimeout = time;
615}
616
617bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
618 InputDevice* device, int32_t keyCode, int32_t scanCode) {
619 if (now < mDisableVirtualKeysTimeout) {
620 ALOGI("Dropping virtual key from device %s because virtual keys are "
621 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100622 device->getName().c_str(),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800623 (mDisableVirtualKeysTimeout - now) * 0.000001,
624 keyCode, scanCode);
625 return true;
626 } else {
627 return false;
628 }
629}
630
631void InputReader::fadePointerLocked() {
632 for (size_t i = 0; i < mDevices.size(); i++) {
633 InputDevice* device = mDevices.valueAt(i);
634 device->fadePointer();
635 }
636}
637
638void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
639 if (when < mNextTimeout) {
640 mNextTimeout = when;
641 mEventHub->wake();
642 }
643}
644
645int32_t InputReader::bumpGenerationLocked() {
646 return ++mGeneration;
647}
648
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800649void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800650 AutoMutex _l(mLock);
651 getInputDevicesLocked(outInputDevices);
652}
653
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800654void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800655 outInputDevices.clear();
656
657 size_t numDevices = mDevices.size();
658 for (size_t i = 0; i < numDevices; i++) {
659 InputDevice* device = mDevices.valueAt(i);
660 if (!device->isIgnored()) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800661 InputDeviceInfo info;
662 device->getDeviceInfo(&info);
663 outInputDevices.push_back(info);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800664 }
665 }
666}
667
668int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
669 int32_t keyCode) {
670 AutoMutex _l(mLock);
671
672 return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
673}
674
675int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
676 int32_t scanCode) {
677 AutoMutex _l(mLock);
678
679 return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
680}
681
682int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
683 AutoMutex _l(mLock);
684
685 return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
686}
687
688int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
689 GetStateFunc getStateFunc) {
690 int32_t result = AKEY_STATE_UNKNOWN;
691 if (deviceId >= 0) {
692 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
693 if (deviceIndex >= 0) {
694 InputDevice* device = mDevices.valueAt(deviceIndex);
695 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
696 result = (device->*getStateFunc)(sourceMask, code);
697 }
698 }
699 } else {
700 size_t numDevices = mDevices.size();
701 for (size_t i = 0; i < numDevices; i++) {
702 InputDevice* device = mDevices.valueAt(i);
703 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
704 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
705 // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
706 int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
707 if (currentResult >= AKEY_STATE_DOWN) {
708 return currentResult;
709 } else if (currentResult == AKEY_STATE_UP) {
710 result = currentResult;
711 }
712 }
713 }
714 }
715 return result;
716}
717
Andrii Kulian763a3a42016-03-08 10:46:16 -0800718void InputReader::toggleCapsLockState(int32_t deviceId) {
719 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
720 if (deviceIndex < 0) {
721 ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
722 return;
723 }
724
725 InputDevice* device = mDevices.valueAt(deviceIndex);
726 if (device->isIgnored()) {
727 return;
728 }
729
730 device->updateMetaState(AKEYCODE_CAPS_LOCK);
731}
732
Michael Wrightd02c5b62014-02-10 15:10:22 -0800733bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
734 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
735 AutoMutex _l(mLock);
736
737 memset(outFlags, 0, numCodes);
738 return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
739}
740
741bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
742 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
743 bool result = false;
744 if (deviceId >= 0) {
745 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
746 if (deviceIndex >= 0) {
747 InputDevice* device = mDevices.valueAt(deviceIndex);
748 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
749 result = device->markSupportedKeyCodes(sourceMask,
750 numCodes, keyCodes, outFlags);
751 }
752 }
753 } else {
754 size_t numDevices = mDevices.size();
755 for (size_t i = 0; i < numDevices; i++) {
756 InputDevice* device = mDevices.valueAt(i);
757 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
758 result |= device->markSupportedKeyCodes(sourceMask,
759 numCodes, keyCodes, outFlags);
760 }
761 }
762 }
763 return result;
764}
765
766void InputReader::requestRefreshConfiguration(uint32_t changes) {
767 AutoMutex _l(mLock);
768
769 if (changes) {
770 bool needWake = !mConfigurationChangesToRefresh;
771 mConfigurationChangesToRefresh |= changes;
772
773 if (needWake) {
774 mEventHub->wake();
775 }
776 }
777}
778
779void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
780 ssize_t repeat, int32_t token) {
781 AutoMutex _l(mLock);
782
783 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
784 if (deviceIndex >= 0) {
785 InputDevice* device = mDevices.valueAt(deviceIndex);
786 device->vibrate(pattern, patternSize, repeat, token);
787 }
788}
789
790void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
791 AutoMutex _l(mLock);
792
793 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
794 if (deviceIndex >= 0) {
795 InputDevice* device = mDevices.valueAt(deviceIndex);
796 device->cancelVibrate(token);
797 }
798}
799
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700800bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
801 AutoMutex _l(mLock);
802
803 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
804 if (deviceIndex >= 0) {
805 InputDevice* device = mDevices.valueAt(deviceIndex);
806 return device->isEnabled();
807 }
808 ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
809 return false;
810}
811
Arthur Hungc23540e2018-11-29 20:42:11 +0800812bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
813 AutoMutex _l(mLock);
814
815 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
816 if (deviceIndex < 0) {
817 ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
818 return false;
819 }
820
821 InputDevice* device = mDevices.valueAt(deviceIndex);
Arthur Hung2c9a3342019-07-23 14:18:59 +0800822 if (!device->isEnabled()) {
823 ALOGW("Ignoring disabled device %s", device->getName().c_str());
824 return false;
825 }
826
827 std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplayId();
Arthur Hungc23540e2018-11-29 20:42:11 +0800828 // No associated display. By default, can dispatch to all displays.
829 if (!associatedDisplayId) {
830 return true;
831 }
832
833 if (*associatedDisplayId == ADISPLAY_ID_NONE) {
Arthur Hung2c9a3342019-07-23 14:18:59 +0800834 ALOGW("Device %s is associated with display ADISPLAY_ID_NONE.", device->getName().c_str());
Arthur Hungc23540e2018-11-29 20:42:11 +0800835 return true;
836 }
837
838 return *associatedDisplayId == displayId;
839}
840
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800841void InputReader::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800842 AutoMutex _l(mLock);
843
844 mEventHub->dump(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800845 dump += "\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800846
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800847 dump += "Input Reader State:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800848
849 for (size_t i = 0; i < mDevices.size(); i++) {
850 mDevices.valueAt(i)->dump(dump);
851 }
852
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800853 dump += INDENT "Configuration:\n";
854 dump += INDENT2 "ExcludedDeviceNames: [";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800855 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
856 if (i != 0) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800857 dump += ", ";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800858 }
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100859 dump += mConfig.excludedDeviceNames[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -0800860 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800861 dump += "]\n";
862 dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800863 mConfig.virtualKeyQuietTime * 0.000001f);
864
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800865 dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
Michael Wrightd02c5b62014-02-10 15:10:22 -0800866 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
867 mConfig.pointerVelocityControlParameters.scale,
868 mConfig.pointerVelocityControlParameters.lowThreshold,
869 mConfig.pointerVelocityControlParameters.highThreshold,
870 mConfig.pointerVelocityControlParameters.acceleration);
871
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800872 dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
Michael Wrightd02c5b62014-02-10 15:10:22 -0800873 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
874 mConfig.wheelVelocityControlParameters.scale,
875 mConfig.wheelVelocityControlParameters.lowThreshold,
876 mConfig.wheelVelocityControlParameters.highThreshold,
877 mConfig.wheelVelocityControlParameters.acceleration);
878
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800879 dump += StringPrintf(INDENT2 "PointerGesture:\n");
880 dump += StringPrintf(INDENT3 "Enabled: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800881 toString(mConfig.pointerGesturesEnabled));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800882 dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800883 mConfig.pointerGestureQuietInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800884 dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800885 mConfig.pointerGestureDragMinSwitchSpeed);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800886 dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800887 mConfig.pointerGestureTapInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800888 dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800889 mConfig.pointerGestureTapDragInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800890 dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800891 mConfig.pointerGestureTapSlop);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800892 dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800893 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800894 dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800895 mConfig.pointerGestureMultitouchMinDistance);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800896 dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800897 mConfig.pointerGestureSwipeTransitionAngleCosine);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800898 dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800899 mConfig.pointerGestureSwipeMaxWidthRatio);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800900 dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800901 mConfig.pointerGestureMovementSpeedRatio);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800902 dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800903 mConfig.pointerGestureZoomSpeedRatio);
Santos Cordonfa5cf462017-04-05 10:37:00 -0700904
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800905 dump += INDENT3 "Viewports:\n";
Santos Cordonfa5cf462017-04-05 10:37:00 -0700906 mConfig.dump(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800907}
908
909void InputReader::monitor() {
910 // Acquire and release the lock to ensure that the reader has not deadlocked.
911 mLock.lock();
912 mEventHub->wake();
913 mReaderIsAliveCondition.wait(mLock);
914 mLock.unlock();
915
916 // Check the EventHub
917 mEventHub->monitor();
918}
919
920
921// --- InputReader::ContextImpl ---
922
923InputReader::ContextImpl::ContextImpl(InputReader* reader) :
924 mReader(reader) {
925}
926
927void InputReader::ContextImpl::updateGlobalMetaState() {
928 // lock is already held by the input loop
929 mReader->updateGlobalMetaStateLocked();
930}
931
932int32_t InputReader::ContextImpl::getGlobalMetaState() {
933 // lock is already held by the input loop
934 return mReader->getGlobalMetaStateLocked();
935}
936
937void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
938 // lock is already held by the input loop
939 mReader->disableVirtualKeysUntilLocked(time);
940}
941
942bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
943 InputDevice* device, int32_t keyCode, int32_t scanCode) {
944 // lock is already held by the input loop
945 return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
946}
947
948void InputReader::ContextImpl::fadePointer() {
949 // lock is already held by the input loop
950 mReader->fadePointerLocked();
951}
952
953void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
954 // lock is already held by the input loop
955 mReader->requestTimeoutAtTimeLocked(when);
956}
957
958int32_t InputReader::ContextImpl::bumpGeneration() {
959 // lock is already held by the input loop
960 return mReader->bumpGenerationLocked();
961}
962
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800963void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
Michael Wright842500e2015-03-13 17:32:02 -0700964 // lock is already held by whatever called refreshConfigurationLocked
965 mReader->getExternalStylusDevicesLocked(outDevices);
966}
967
968void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
969 mReader->dispatchExternalStylusState(state);
970}
971
Michael Wrightd02c5b62014-02-10 15:10:22 -0800972InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
973 return mReader->mPolicy.get();
974}
975
976InputListenerInterface* InputReader::ContextImpl::getListener() {
977 return mReader->mQueuedListener.get();
978}
979
980EventHubInterface* InputReader::ContextImpl::getEventHub() {
981 return mReader->mEventHub.get();
982}
983
Prabir Pradhan42611e02018-11-27 14:04:02 -0800984uint32_t InputReader::ContextImpl::getNextSequenceNum() {
985 return (mReader->mNextSequenceNum)++;
986}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800987
Michael Wrightd02c5b62014-02-10 15:10:22 -0800988// --- InputDevice ---
989
990InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
991 int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
992 mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
993 mIdentifier(identifier), mClasses(classes),
Tim Kilbourn063ff532015-04-08 10:26:18 -0700994 mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800995}
996
997InputDevice::~InputDevice() {
998 size_t numMappers = mMappers.size();
999 for (size_t i = 0; i < numMappers; i++) {
1000 delete mMappers[i];
1001 }
1002 mMappers.clear();
1003}
1004
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001005bool InputDevice::isEnabled() {
1006 return getEventHub()->isDeviceEnabled(mId);
1007}
1008
1009void InputDevice::setEnabled(bool enabled, nsecs_t when) {
Arthur Hung2c9a3342019-07-23 14:18:59 +08001010 if (enabled && mAssociatedDisplayPort && !mAssociatedViewport) {
1011 ALOGW("Cannot enable input device %s because it is associated with port %" PRIu8 ", "
1012 "but the corresponding viewport is not found",
1013 getName().c_str(), *mAssociatedDisplayPort);
1014 enabled = false;
1015 }
1016
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001017 if (isEnabled() == enabled) {
1018 return;
1019 }
1020
1021 if (enabled) {
1022 getEventHub()->enableDevice(mId);
1023 reset(when);
1024 } else {
1025 reset(when);
1026 getEventHub()->disableDevice(mId);
1027 }
1028 // Must change generation to flag this device as changed
1029 bumpGeneration();
1030}
1031
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001032void InputDevice::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001033 InputDeviceInfo deviceInfo;
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -07001034 getDeviceInfo(&deviceInfo);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001035
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001036 dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001037 deviceInfo.getDisplayName().c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001038 dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
1039 dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07001040 dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
1041 if (mAssociatedDisplayPort) {
1042 dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
1043 } else {
1044 dump += "<none>\n";
1045 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001046 dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
1047 dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
1048 dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001049
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001050 const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
1051 if (!ranges.empty()) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001052 dump += INDENT2 "Motion Ranges:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08001053 for (size_t i = 0; i < ranges.size(); i++) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001054 const InputDeviceInfo::MotionRange& range = ranges[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08001055 const char* label = getAxisLabel(range.axis);
1056 char name[32];
1057 if (label) {
1058 strncpy(name, label, sizeof(name));
1059 name[sizeof(name) - 1] = '\0';
1060 } else {
1061 snprintf(name, sizeof(name), "%d", range.axis);
1062 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001063 dump += StringPrintf(INDENT3 "%s: source=0x%08x, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08001064 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
1065 name, range.source, range.min, range.max, range.flat, range.fuzz,
1066 range.resolution);
1067 }
1068 }
1069
1070 size_t numMappers = mMappers.size();
1071 for (size_t i = 0; i < numMappers; i++) {
1072 InputMapper* mapper = mMappers[i];
1073 mapper->dump(dump);
1074 }
1075}
1076
1077void InputDevice::addMapper(InputMapper* mapper) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001078 mMappers.push_back(mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001079}
1080
1081void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
1082 mSources = 0;
1083
1084 if (!isIgnored()) {
1085 if (!changes) { // first time only
1086 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
1087 }
1088
1089 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
1090 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
1091 sp<KeyCharacterMap> keyboardLayout =
1092 mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
1093 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
1094 bumpGeneration();
1095 }
1096 }
1097 }
1098
1099 if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
1100 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001101 std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001102 if (mAlias != alias) {
1103 mAlias = alias;
1104 bumpGeneration();
1105 }
1106 }
1107 }
1108
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001109 if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
Siarhei Vishniakouc6f61192019-07-23 18:12:31 +00001110 auto it = config->disabledDevices.find(mId);
1111 bool enabled = it == config->disabledDevices.end();
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001112 setEnabled(enabled, when);
1113 }
1114
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07001115 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
1116 // In most situations, no port will be specified.
1117 mAssociatedDisplayPort = std::nullopt;
Arthur Hung2c9a3342019-07-23 14:18:59 +08001118 mAssociatedViewport = std::nullopt;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07001119 // Find the display port that corresponds to the current input port.
1120 const std::string& inputPort = mIdentifier.location;
1121 if (!inputPort.empty()) {
1122 const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
1123 const auto& displayPort = ports.find(inputPort);
1124 if (displayPort != ports.end()) {
1125 mAssociatedDisplayPort = std::make_optional(displayPort->second);
1126 }
1127 }
Arthur Hung2c9a3342019-07-23 14:18:59 +08001128
1129 // If the device was explicitly disabled by the user, it would be present in the
1130 // "disabledDevices" list. If it is associated with a specific display, and it was not
1131 // explicitly disabled, then enable/disable the device based on whether we can find the
1132 // corresponding viewport.
1133 bool enabled = (config->disabledDevices.find(mId) == config->disabledDevices.end());
1134 if (mAssociatedDisplayPort) {
1135 mAssociatedViewport = config->getDisplayViewportByPort(*mAssociatedDisplayPort);
1136 if (!mAssociatedViewport) {
1137 ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
1138 "but the corresponding viewport is not found.",
1139 getName().c_str(), *mAssociatedDisplayPort);
1140 enabled = false;
1141 }
1142 }
1143
Arthur Hung9da14732019-09-02 16:16:58 +08001144 if (changes) {
1145 // For first-time configuration, only allow device to be disabled after mappers have
1146 // finished configuring. This is because we need to read some of the properties from
1147 // the device's open fd.
1148 setEnabled(enabled, when);
1149 }
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07001150 }
1151
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001152 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001153 mapper->configure(when, config, changes);
1154 mSources |= mapper->getSources();
1155 }
Arthur Hung9da14732019-09-02 16:16:58 +08001156
1157 // If a device is just plugged but it might be disabled, we need to update some info like
1158 // axis range of touch from each InputMapper first, then disable it.
1159 if (!changes) {
1160 setEnabled(config->disabledDevices.find(mId) == config->disabledDevices.end(), when);
1161 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08001162 }
1163}
1164
1165void InputDevice::reset(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001166 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001167 mapper->reset(when);
1168 }
1169
1170 mContext->updateGlobalMetaState();
1171
1172 notifyReset(when);
1173}
1174
1175void InputDevice::process(const RawEvent* rawEvents, size_t count) {
1176 // Process all of the events in order for each mapper.
1177 // We cannot simply ask each mapper to process them in bulk because mappers may
1178 // have side-effects that must be interleaved. For example, joystick movement events and
1179 // gamepad button presses are handled by different mappers but they should be dispatched
1180 // in the order received.
Ivan Lozano96f12992017-11-09 14:45:38 -08001181 for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001182#if DEBUG_RAW_EVENTS
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07001183 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08001184 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
1185 rawEvent->when);
1186#endif
1187
1188 if (mDropUntilNextSync) {
1189 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1190 mDropUntilNextSync = false;
1191#if DEBUG_RAW_EVENTS
1192 ALOGD("Recovered from input event buffer overrun.");
1193#endif
1194 } else {
1195#if DEBUG_RAW_EVENTS
1196 ALOGD("Dropped input event while waiting for next input sync.");
1197#endif
1198 }
1199 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001200 ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001201 mDropUntilNextSync = true;
1202 reset(rawEvent->when);
1203 } else {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001204 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001205 mapper->process(rawEvent);
1206 }
1207 }
Ivan Lozano96f12992017-11-09 14:45:38 -08001208 --count;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001209 }
1210}
1211
1212void InputDevice::timeoutExpired(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001213 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001214 mapper->timeoutExpired(when);
1215 }
1216}
1217
Michael Wright842500e2015-03-13 17:32:02 -07001218void InputDevice::updateExternalStylusState(const StylusState& state) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001219 for (InputMapper* mapper : mMappers) {
Michael Wright842500e2015-03-13 17:32:02 -07001220 mapper->updateExternalStylusState(state);
1221 }
1222}
1223
Michael Wrightd02c5b62014-02-10 15:10:22 -08001224void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
1225 outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
Tim Kilbourn063ff532015-04-08 10:26:18 -07001226 mIsExternal, mHasMic);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001227 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001228 mapper->populateDeviceInfo(outDeviceInfo);
1229 }
1230}
1231
1232int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1233 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
1234}
1235
1236int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1237 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
1238}
1239
1240int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1241 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
1242}
1243
1244int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
1245 int32_t result = AKEY_STATE_UNKNOWN;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001246 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001247 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1248 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
1249 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
1250 int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
1251 if (currentResult >= AKEY_STATE_DOWN) {
1252 return currentResult;
1253 } else if (currentResult == AKEY_STATE_UP) {
1254 result = currentResult;
1255 }
1256 }
1257 }
1258 return result;
1259}
1260
1261bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1262 const int32_t* keyCodes, uint8_t* outFlags) {
1263 bool result = false;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001264 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001265 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1266 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1267 }
1268 }
1269 return result;
1270}
1271
1272void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1273 int32_t token) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001274 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001275 mapper->vibrate(pattern, patternSize, repeat, token);
1276 }
1277}
1278
1279void InputDevice::cancelVibrate(int32_t token) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001280 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001281 mapper->cancelVibrate(token);
1282 }
1283}
1284
Jeff Brownc9aa6282015-02-11 19:03:28 -08001285void InputDevice::cancelTouch(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001286 for (InputMapper* mapper : mMappers) {
Jeff Brownc9aa6282015-02-11 19:03:28 -08001287 mapper->cancelTouch(when);
1288 }
1289}
1290
Michael Wrightd02c5b62014-02-10 15:10:22 -08001291int32_t InputDevice::getMetaState() {
1292 int32_t result = 0;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001293 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001294 result |= mapper->getMetaState();
1295 }
1296 return result;
1297}
1298
Andrii Kulian763a3a42016-03-08 10:46:16 -08001299void InputDevice::updateMetaState(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001300 for (InputMapper* mapper : mMappers) {
1301 mapper->updateMetaState(keyCode);
Andrii Kulian763a3a42016-03-08 10:46:16 -08001302 }
1303}
1304
Michael Wrightd02c5b62014-02-10 15:10:22 -08001305void InputDevice::fadePointer() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001306 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001307 mapper->fadePointer();
1308 }
1309}
1310
1311void InputDevice::bumpGeneration() {
1312 mGeneration = mContext->bumpGeneration();
1313}
1314
1315void InputDevice::notifyReset(nsecs_t when) {
Prabir Pradhan42611e02018-11-27 14:04:02 -08001316 NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001317 mContext->getListener()->notifyDeviceReset(&args);
1318}
1319
Arthur Hung2c9a3342019-07-23 14:18:59 +08001320std::optional<int32_t> InputDevice::getAssociatedDisplayId() {
1321 // Check if we had associated to the specific display.
1322 if (mAssociatedViewport) {
1323 return mAssociatedViewport->displayId;
1324 }
1325
1326 // No associated display port, check if some InputMapper is associated.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001327 for (InputMapper* mapper : mMappers) {
Arthur Hung2c9a3342019-07-23 14:18:59 +08001328 std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplayId();
Arthur Hungc23540e2018-11-29 20:42:11 +08001329 if (associatedDisplayId) {
1330 return associatedDisplayId;
1331 }
1332 }
1333
1334 return std::nullopt;
1335}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001336
1337// --- CursorButtonAccumulator ---
1338
1339CursorButtonAccumulator::CursorButtonAccumulator() {
1340 clearButtons();
1341}
1342
1343void CursorButtonAccumulator::reset(InputDevice* device) {
1344 mBtnLeft = device->isKeyPressed(BTN_LEFT);
1345 mBtnRight = device->isKeyPressed(BTN_RIGHT);
1346 mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
1347 mBtnBack = device->isKeyPressed(BTN_BACK);
1348 mBtnSide = device->isKeyPressed(BTN_SIDE);
1349 mBtnForward = device->isKeyPressed(BTN_FORWARD);
1350 mBtnExtra = device->isKeyPressed(BTN_EXTRA);
1351 mBtnTask = device->isKeyPressed(BTN_TASK);
1352}
1353
1354void CursorButtonAccumulator::clearButtons() {
1355 mBtnLeft = 0;
1356 mBtnRight = 0;
1357 mBtnMiddle = 0;
1358 mBtnBack = 0;
1359 mBtnSide = 0;
1360 mBtnForward = 0;
1361 mBtnExtra = 0;
1362 mBtnTask = 0;
1363}
1364
1365void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1366 if (rawEvent->type == EV_KEY) {
1367 switch (rawEvent->code) {
1368 case BTN_LEFT:
1369 mBtnLeft = rawEvent->value;
1370 break;
1371 case BTN_RIGHT:
1372 mBtnRight = rawEvent->value;
1373 break;
1374 case BTN_MIDDLE:
1375 mBtnMiddle = rawEvent->value;
1376 break;
1377 case BTN_BACK:
1378 mBtnBack = rawEvent->value;
1379 break;
1380 case BTN_SIDE:
1381 mBtnSide = rawEvent->value;
1382 break;
1383 case BTN_FORWARD:
1384 mBtnForward = rawEvent->value;
1385 break;
1386 case BTN_EXTRA:
1387 mBtnExtra = rawEvent->value;
1388 break;
1389 case BTN_TASK:
1390 mBtnTask = rawEvent->value;
1391 break;
1392 }
1393 }
1394}
1395
1396uint32_t CursorButtonAccumulator::getButtonState() const {
1397 uint32_t result = 0;
1398 if (mBtnLeft) {
1399 result |= AMOTION_EVENT_BUTTON_PRIMARY;
1400 }
1401 if (mBtnRight) {
1402 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1403 }
1404 if (mBtnMiddle) {
1405 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1406 }
1407 if (mBtnBack || mBtnSide) {
1408 result |= AMOTION_EVENT_BUTTON_BACK;
1409 }
1410 if (mBtnForward || mBtnExtra) {
1411 result |= AMOTION_EVENT_BUTTON_FORWARD;
1412 }
1413 return result;
1414}
1415
1416
1417// --- CursorMotionAccumulator ---
1418
1419CursorMotionAccumulator::CursorMotionAccumulator() {
1420 clearRelativeAxes();
1421}
1422
1423void CursorMotionAccumulator::reset(InputDevice* device) {
1424 clearRelativeAxes();
1425}
1426
1427void CursorMotionAccumulator::clearRelativeAxes() {
1428 mRelX = 0;
1429 mRelY = 0;
1430}
1431
1432void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1433 if (rawEvent->type == EV_REL) {
1434 switch (rawEvent->code) {
1435 case REL_X:
1436 mRelX = rawEvent->value;
1437 break;
1438 case REL_Y:
1439 mRelY = rawEvent->value;
1440 break;
1441 }
1442 }
1443}
1444
1445void CursorMotionAccumulator::finishSync() {
1446 clearRelativeAxes();
1447}
1448
1449
1450// --- CursorScrollAccumulator ---
1451
1452CursorScrollAccumulator::CursorScrollAccumulator() :
1453 mHaveRelWheel(false), mHaveRelHWheel(false) {
1454 clearRelativeAxes();
1455}
1456
1457void CursorScrollAccumulator::configure(InputDevice* device) {
1458 mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1459 mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1460}
1461
1462void CursorScrollAccumulator::reset(InputDevice* device) {
1463 clearRelativeAxes();
1464}
1465
1466void CursorScrollAccumulator::clearRelativeAxes() {
1467 mRelWheel = 0;
1468 mRelHWheel = 0;
1469}
1470
1471void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
1472 if (rawEvent->type == EV_REL) {
1473 switch (rawEvent->code) {
1474 case REL_WHEEL:
1475 mRelWheel = rawEvent->value;
1476 break;
1477 case REL_HWHEEL:
1478 mRelHWheel = rawEvent->value;
1479 break;
1480 }
1481 }
1482}
1483
1484void CursorScrollAccumulator::finishSync() {
1485 clearRelativeAxes();
1486}
1487
1488
1489// --- TouchButtonAccumulator ---
1490
1491TouchButtonAccumulator::TouchButtonAccumulator() :
1492 mHaveBtnTouch(false), mHaveStylus(false) {
1493 clearButtons();
1494}
1495
1496void TouchButtonAccumulator::configure(InputDevice* device) {
1497 mHaveBtnTouch = device->hasKey(BTN_TOUCH);
1498 mHaveStylus = device->hasKey(BTN_TOOL_PEN)
1499 || device->hasKey(BTN_TOOL_RUBBER)
1500 || device->hasKey(BTN_TOOL_BRUSH)
1501 || device->hasKey(BTN_TOOL_PENCIL)
1502 || device->hasKey(BTN_TOOL_AIRBRUSH);
1503}
1504
1505void TouchButtonAccumulator::reset(InputDevice* device) {
1506 mBtnTouch = device->isKeyPressed(BTN_TOUCH);
1507 mBtnStylus = device->isKeyPressed(BTN_STYLUS);
Michael Wright842500e2015-03-13 17:32:02 -07001508 // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
1509 mBtnStylus2 =
1510 device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001511 mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
1512 mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
1513 mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
1514 mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
1515 mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
1516 mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
1517 mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
1518 mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
1519 mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
1520 mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
1521 mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
1522}
1523
1524void TouchButtonAccumulator::clearButtons() {
1525 mBtnTouch = 0;
1526 mBtnStylus = 0;
1527 mBtnStylus2 = 0;
1528 mBtnToolFinger = 0;
1529 mBtnToolPen = 0;
1530 mBtnToolRubber = 0;
1531 mBtnToolBrush = 0;
1532 mBtnToolPencil = 0;
1533 mBtnToolAirbrush = 0;
1534 mBtnToolMouse = 0;
1535 mBtnToolLens = 0;
1536 mBtnToolDoubleTap = 0;
1537 mBtnToolTripleTap = 0;
1538 mBtnToolQuadTap = 0;
1539}
1540
1541void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1542 if (rawEvent->type == EV_KEY) {
1543 switch (rawEvent->code) {
1544 case BTN_TOUCH:
1545 mBtnTouch = rawEvent->value;
1546 break;
1547 case BTN_STYLUS:
1548 mBtnStylus = rawEvent->value;
1549 break;
1550 case BTN_STYLUS2:
Michael Wright842500e2015-03-13 17:32:02 -07001551 case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
Michael Wrightd02c5b62014-02-10 15:10:22 -08001552 mBtnStylus2 = rawEvent->value;
1553 break;
1554 case BTN_TOOL_FINGER:
1555 mBtnToolFinger = rawEvent->value;
1556 break;
1557 case BTN_TOOL_PEN:
1558 mBtnToolPen = rawEvent->value;
1559 break;
1560 case BTN_TOOL_RUBBER:
1561 mBtnToolRubber = rawEvent->value;
1562 break;
1563 case BTN_TOOL_BRUSH:
1564 mBtnToolBrush = rawEvent->value;
1565 break;
1566 case BTN_TOOL_PENCIL:
1567 mBtnToolPencil = rawEvent->value;
1568 break;
1569 case BTN_TOOL_AIRBRUSH:
1570 mBtnToolAirbrush = rawEvent->value;
1571 break;
1572 case BTN_TOOL_MOUSE:
1573 mBtnToolMouse = rawEvent->value;
1574 break;
1575 case BTN_TOOL_LENS:
1576 mBtnToolLens = rawEvent->value;
1577 break;
1578 case BTN_TOOL_DOUBLETAP:
1579 mBtnToolDoubleTap = rawEvent->value;
1580 break;
1581 case BTN_TOOL_TRIPLETAP:
1582 mBtnToolTripleTap = rawEvent->value;
1583 break;
1584 case BTN_TOOL_QUADTAP:
1585 mBtnToolQuadTap = rawEvent->value;
1586 break;
1587 }
1588 }
1589}
1590
1591uint32_t TouchButtonAccumulator::getButtonState() const {
1592 uint32_t result = 0;
1593 if (mBtnStylus) {
Michael Wright7b159c92015-05-14 14:48:03 +01001594 result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001595 }
1596 if (mBtnStylus2) {
Michael Wright7b159c92015-05-14 14:48:03 +01001597 result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001598 }
1599 return result;
1600}
1601
1602int32_t TouchButtonAccumulator::getToolType() const {
1603 if (mBtnToolMouse || mBtnToolLens) {
1604 return AMOTION_EVENT_TOOL_TYPE_MOUSE;
1605 }
1606 if (mBtnToolRubber) {
1607 return AMOTION_EVENT_TOOL_TYPE_ERASER;
1608 }
1609 if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
1610 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1611 }
1612 if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
1613 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1614 }
1615 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1616}
1617
1618bool TouchButtonAccumulator::isToolActive() const {
1619 return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
1620 || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
1621 || mBtnToolMouse || mBtnToolLens
1622 || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
1623}
1624
1625bool TouchButtonAccumulator::isHovering() const {
1626 return mHaveBtnTouch && !mBtnTouch;
1627}
1628
1629bool TouchButtonAccumulator::hasStylus() const {
1630 return mHaveStylus;
1631}
1632
1633
1634// --- RawPointerAxes ---
1635
1636RawPointerAxes::RawPointerAxes() {
1637 clear();
1638}
1639
1640void RawPointerAxes::clear() {
1641 x.clear();
1642 y.clear();
1643 pressure.clear();
1644 touchMajor.clear();
1645 touchMinor.clear();
1646 toolMajor.clear();
1647 toolMinor.clear();
1648 orientation.clear();
1649 distance.clear();
1650 tiltX.clear();
1651 tiltY.clear();
1652 trackingId.clear();
1653 slot.clear();
1654}
1655
1656
1657// --- RawPointerData ---
1658
1659RawPointerData::RawPointerData() {
1660 clear();
1661}
1662
1663void RawPointerData::clear() {
1664 pointerCount = 0;
1665 clearIdBits();
1666}
1667
1668void RawPointerData::copyFrom(const RawPointerData& other) {
1669 pointerCount = other.pointerCount;
1670 hoveringIdBits = other.hoveringIdBits;
1671 touchingIdBits = other.touchingIdBits;
1672
1673 for (uint32_t i = 0; i < pointerCount; i++) {
1674 pointers[i] = other.pointers[i];
1675
1676 int id = pointers[i].id;
1677 idToIndex[id] = other.idToIndex[id];
1678 }
1679}
1680
1681void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
1682 float x = 0, y = 0;
1683 uint32_t count = touchingIdBits.count();
1684 if (count) {
1685 for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
1686 uint32_t id = idBits.clearFirstMarkedBit();
1687 const Pointer& pointer = pointerForId(id);
1688 x += pointer.x;
1689 y += pointer.y;
1690 }
1691 x /= count;
1692 y /= count;
1693 }
1694 *outX = x;
1695 *outY = y;
1696}
1697
1698
1699// --- CookedPointerData ---
1700
1701CookedPointerData::CookedPointerData() {
1702 clear();
1703}
1704
1705void CookedPointerData::clear() {
1706 pointerCount = 0;
1707 hoveringIdBits.clear();
1708 touchingIdBits.clear();
1709}
1710
1711void CookedPointerData::copyFrom(const CookedPointerData& other) {
1712 pointerCount = other.pointerCount;
1713 hoveringIdBits = other.hoveringIdBits;
1714 touchingIdBits = other.touchingIdBits;
1715
1716 for (uint32_t i = 0; i < pointerCount; i++) {
1717 pointerProperties[i].copyFrom(other.pointerProperties[i]);
1718 pointerCoords[i].copyFrom(other.pointerCoords[i]);
1719
1720 int id = pointerProperties[i].id;
1721 idToIndex[id] = other.idToIndex[id];
1722 }
1723}
1724
1725
1726// --- SingleTouchMotionAccumulator ---
1727
1728SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1729 clearAbsoluteAxes();
1730}
1731
1732void SingleTouchMotionAccumulator::reset(InputDevice* device) {
1733 mAbsX = device->getAbsoluteAxisValue(ABS_X);
1734 mAbsY = device->getAbsoluteAxisValue(ABS_Y);
1735 mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
1736 mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
1737 mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
1738 mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
1739 mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
1740}
1741
1742void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1743 mAbsX = 0;
1744 mAbsY = 0;
1745 mAbsPressure = 0;
1746 mAbsToolWidth = 0;
1747 mAbsDistance = 0;
1748 mAbsTiltX = 0;
1749 mAbsTiltY = 0;
1750}
1751
1752void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1753 if (rawEvent->type == EV_ABS) {
1754 switch (rawEvent->code) {
1755 case ABS_X:
1756 mAbsX = rawEvent->value;
1757 break;
1758 case ABS_Y:
1759 mAbsY = rawEvent->value;
1760 break;
1761 case ABS_PRESSURE:
1762 mAbsPressure = rawEvent->value;
1763 break;
1764 case ABS_TOOL_WIDTH:
1765 mAbsToolWidth = rawEvent->value;
1766 break;
1767 case ABS_DISTANCE:
1768 mAbsDistance = rawEvent->value;
1769 break;
1770 case ABS_TILT_X:
1771 mAbsTiltX = rawEvent->value;
1772 break;
1773 case ABS_TILT_Y:
1774 mAbsTiltY = rawEvent->value;
1775 break;
1776 }
1777 }
1778}
1779
1780
1781// --- MultiTouchMotionAccumulator ---
1782
Atif Niyaz21da0ff2019-06-28 13:22:51 -07001783MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
1784 : mCurrentSlot(-1),
1785 mSlots(nullptr),
1786 mSlotCount(0),
1787 mUsingSlotsProtocol(false),
1788 mHaveStylus(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001789
1790MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1791 delete[] mSlots;
1792}
1793
1794void MultiTouchMotionAccumulator::configure(InputDevice* device,
1795 size_t slotCount, bool usingSlotsProtocol) {
1796 mSlotCount = slotCount;
1797 mUsingSlotsProtocol = usingSlotsProtocol;
1798 mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
1799
1800 delete[] mSlots;
1801 mSlots = new Slot[slotCount];
1802}
1803
1804void MultiTouchMotionAccumulator::reset(InputDevice* device) {
1805 // Unfortunately there is no way to read the initial contents of the slots.
1806 // So when we reset the accumulator, we must assume they are all zeroes.
1807 if (mUsingSlotsProtocol) {
1808 // Query the driver for the current slot index and use it as the initial slot
1809 // before we start reading events from the device. It is possible that the
1810 // current slot index will not be the same as it was when the first event was
1811 // written into the evdev buffer, which means the input mapper could start
1812 // out of sync with the initial state of the events in the evdev buffer.
1813 // In the extremely unlikely case that this happens, the data from
1814 // two slots will be confused until the next ABS_MT_SLOT event is received.
1815 // This can cause the touch point to "jump", but at least there will be
1816 // no stuck touches.
1817 int32_t initialSlot;
1818 status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
1819 ABS_MT_SLOT, &initialSlot);
1820 if (status) {
1821 ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
1822 initialSlot = -1;
1823 }
1824 clearSlots(initialSlot);
1825 } else {
1826 clearSlots(-1);
1827 }
1828}
1829
1830void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
1831 if (mSlots) {
1832 for (size_t i = 0; i < mSlotCount; i++) {
1833 mSlots[i].clear();
1834 }
1835 }
1836 mCurrentSlot = initialSlot;
1837}
1838
1839void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1840 if (rawEvent->type == EV_ABS) {
1841 bool newSlot = false;
1842 if (mUsingSlotsProtocol) {
1843 if (rawEvent->code == ABS_MT_SLOT) {
1844 mCurrentSlot = rawEvent->value;
1845 newSlot = true;
1846 }
1847 } else if (mCurrentSlot < 0) {
1848 mCurrentSlot = 0;
1849 }
1850
1851 if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1852#if DEBUG_POINTERS
1853 if (newSlot) {
1854 ALOGW("MultiTouch device emitted invalid slot index %d but it "
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07001855 "should be between 0 and %zd; ignoring this slot.",
Michael Wrightd02c5b62014-02-10 15:10:22 -08001856 mCurrentSlot, mSlotCount - 1);
1857 }
1858#endif
1859 } else {
1860 Slot* slot = &mSlots[mCurrentSlot];
1861
1862 switch (rawEvent->code) {
1863 case ABS_MT_POSITION_X:
1864 slot->mInUse = true;
1865 slot->mAbsMTPositionX = rawEvent->value;
1866 break;
1867 case ABS_MT_POSITION_Y:
1868 slot->mInUse = true;
1869 slot->mAbsMTPositionY = rawEvent->value;
1870 break;
1871 case ABS_MT_TOUCH_MAJOR:
1872 slot->mInUse = true;
1873 slot->mAbsMTTouchMajor = rawEvent->value;
1874 break;
1875 case ABS_MT_TOUCH_MINOR:
1876 slot->mInUse = true;
1877 slot->mAbsMTTouchMinor = rawEvent->value;
1878 slot->mHaveAbsMTTouchMinor = true;
1879 break;
1880 case ABS_MT_WIDTH_MAJOR:
1881 slot->mInUse = true;
1882 slot->mAbsMTWidthMajor = rawEvent->value;
1883 break;
1884 case ABS_MT_WIDTH_MINOR:
1885 slot->mInUse = true;
1886 slot->mAbsMTWidthMinor = rawEvent->value;
1887 slot->mHaveAbsMTWidthMinor = true;
1888 break;
1889 case ABS_MT_ORIENTATION:
1890 slot->mInUse = true;
1891 slot->mAbsMTOrientation = rawEvent->value;
1892 break;
1893 case ABS_MT_TRACKING_ID:
1894 if (mUsingSlotsProtocol && rawEvent->value < 0) {
1895 // The slot is no longer in use but it retains its previous contents,
1896 // which may be reused for subsequent touches.
1897 slot->mInUse = false;
1898 } else {
1899 slot->mInUse = true;
1900 slot->mAbsMTTrackingId = rawEvent->value;
1901 }
1902 break;
1903 case ABS_MT_PRESSURE:
1904 slot->mInUse = true;
1905 slot->mAbsMTPressure = rawEvent->value;
1906 break;
1907 case ABS_MT_DISTANCE:
1908 slot->mInUse = true;
1909 slot->mAbsMTDistance = rawEvent->value;
1910 break;
1911 case ABS_MT_TOOL_TYPE:
1912 slot->mInUse = true;
1913 slot->mAbsMTToolType = rawEvent->value;
1914 slot->mHaveAbsMTToolType = true;
1915 break;
1916 }
1917 }
1918 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
1919 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1920 mCurrentSlot += 1;
1921 }
1922}
1923
1924void MultiTouchMotionAccumulator::finishSync() {
1925 if (!mUsingSlotsProtocol) {
1926 clearSlots(-1);
1927 }
1928}
1929
1930bool MultiTouchMotionAccumulator::hasStylus() const {
1931 return mHaveStylus;
1932}
1933
1934
1935// --- MultiTouchMotionAccumulator::Slot ---
1936
1937MultiTouchMotionAccumulator::Slot::Slot() {
1938 clear();
1939}
1940
1941void MultiTouchMotionAccumulator::Slot::clear() {
1942 mInUse = false;
1943 mHaveAbsMTTouchMinor = false;
1944 mHaveAbsMTWidthMinor = false;
1945 mHaveAbsMTToolType = false;
1946 mAbsMTPositionX = 0;
1947 mAbsMTPositionY = 0;
1948 mAbsMTTouchMajor = 0;
1949 mAbsMTTouchMinor = 0;
1950 mAbsMTWidthMajor = 0;
1951 mAbsMTWidthMinor = 0;
1952 mAbsMTOrientation = 0;
1953 mAbsMTTrackingId = -1;
1954 mAbsMTPressure = 0;
1955 mAbsMTDistance = 0;
1956 mAbsMTToolType = 0;
1957}
1958
1959int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1960 if (mHaveAbsMTToolType) {
1961 switch (mAbsMTToolType) {
1962 case MT_TOOL_FINGER:
1963 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1964 case MT_TOOL_PEN:
1965 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1966 }
1967 }
1968 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1969}
1970
1971
1972// --- InputMapper ---
1973
1974InputMapper::InputMapper(InputDevice* device) :
1975 mDevice(device), mContext(device->getContext()) {
1976}
1977
1978InputMapper::~InputMapper() {
1979}
1980
1981void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1982 info->addSource(getSources());
1983}
1984
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001985void InputMapper::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001986}
1987
1988void InputMapper::configure(nsecs_t when,
1989 const InputReaderConfiguration* config, uint32_t changes) {
1990}
1991
1992void InputMapper::reset(nsecs_t when) {
1993}
1994
1995void InputMapper::timeoutExpired(nsecs_t when) {
1996}
1997
1998int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1999 return AKEY_STATE_UNKNOWN;
2000}
2001
2002int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2003 return AKEY_STATE_UNKNOWN;
2004}
2005
2006int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
2007 return AKEY_STATE_UNKNOWN;
2008}
2009
2010bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2011 const int32_t* keyCodes, uint8_t* outFlags) {
2012 return false;
2013}
2014
2015void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
2016 int32_t token) {
2017}
2018
2019void InputMapper::cancelVibrate(int32_t token) {
2020}
2021
Jeff Brownc9aa6282015-02-11 19:03:28 -08002022void InputMapper::cancelTouch(nsecs_t when) {
2023}
2024
Michael Wrightd02c5b62014-02-10 15:10:22 -08002025int32_t InputMapper::getMetaState() {
2026 return 0;
2027}
2028
Andrii Kulian763a3a42016-03-08 10:46:16 -08002029void InputMapper::updateMetaState(int32_t keyCode) {
2030}
2031
Michael Wright842500e2015-03-13 17:32:02 -07002032void InputMapper::updateExternalStylusState(const StylusState& state) {
2033
2034}
2035
Michael Wrightd02c5b62014-02-10 15:10:22 -08002036void InputMapper::fadePointer() {
2037}
2038
2039status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
2040 return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
2041}
2042
2043void InputMapper::bumpGeneration() {
2044 mDevice->bumpGeneration();
2045}
2046
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002047void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002048 const RawAbsoluteAxisInfo& axis, const char* name) {
2049 if (axis.valid) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002050 dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002051 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
2052 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002053 dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002054 }
2055}
2056
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002057void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
2058 dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
2059 dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
2060 dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
2061 dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
Michael Wright842500e2015-03-13 17:32:02 -07002062}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002063
2064// --- SwitchInputMapper ---
2065
2066SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002067 InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002068}
2069
2070SwitchInputMapper::~SwitchInputMapper() {
2071}
2072
2073uint32_t SwitchInputMapper::getSources() {
2074 return AINPUT_SOURCE_SWITCH;
2075}
2076
2077void SwitchInputMapper::process(const RawEvent* rawEvent) {
2078 switch (rawEvent->type) {
2079 case EV_SW:
2080 processSwitch(rawEvent->code, rawEvent->value);
2081 break;
2082
2083 case EV_SYN:
2084 if (rawEvent->code == SYN_REPORT) {
2085 sync(rawEvent->when);
2086 }
2087 }
2088}
2089
2090void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
2091 if (switchCode >= 0 && switchCode < 32) {
2092 if (switchValue) {
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002093 mSwitchValues |= 1 << switchCode;
2094 } else {
2095 mSwitchValues &= ~(1 << switchCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002096 }
2097 mUpdatedSwitchMask |= 1 << switchCode;
2098 }
2099}
2100
2101void SwitchInputMapper::sync(nsecs_t when) {
2102 if (mUpdatedSwitchMask) {
Michael Wright3da3b842014-08-29 16:16:26 -07002103 uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
Prabir Pradhan42611e02018-11-27 14:04:02 -08002104 NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
2105 mUpdatedSwitchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002106 getListener()->notifySwitch(&args);
2107
Michael Wrightd02c5b62014-02-10 15:10:22 -08002108 mUpdatedSwitchMask = 0;
2109 }
2110}
2111
2112int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
2113 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
2114}
2115
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002116void SwitchInputMapper::dump(std::string& dump) {
2117 dump += INDENT2 "Switch Input Mapper:\n";
2118 dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002119}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002120
2121// --- VibratorInputMapper ---
2122
2123VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
2124 InputMapper(device), mVibrating(false) {
2125}
2126
2127VibratorInputMapper::~VibratorInputMapper() {
2128}
2129
2130uint32_t VibratorInputMapper::getSources() {
2131 return 0;
2132}
2133
2134void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2135 InputMapper::populateDeviceInfo(info);
2136
2137 info->setVibrator(true);
2138}
2139
2140void VibratorInputMapper::process(const RawEvent* rawEvent) {
2141 // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
2142}
2143
2144void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
2145 int32_t token) {
2146#if DEBUG_VIBRATOR
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002147 std::string patternStr;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002148 for (size_t i = 0; i < patternSize; i++) {
2149 if (i != 0) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002150 patternStr += ", ";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002151 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002152 patternStr += StringPrintf("%" PRId64, pattern[i]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002153 }
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07002154 ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002155 getDeviceId(), patternStr.c_str(), repeat, token);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002156#endif
2157
2158 mVibrating = true;
2159 memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
2160 mPatternSize = patternSize;
2161 mRepeat = repeat;
2162 mToken = token;
2163 mIndex = -1;
2164
2165 nextStep();
2166}
2167
2168void VibratorInputMapper::cancelVibrate(int32_t token) {
2169#if DEBUG_VIBRATOR
2170 ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
2171#endif
2172
2173 if (mVibrating && mToken == token) {
2174 stopVibrating();
2175 }
2176}
2177
2178void VibratorInputMapper::timeoutExpired(nsecs_t when) {
2179 if (mVibrating) {
2180 if (when >= mNextStepTime) {
2181 nextStep();
2182 } else {
2183 getContext()->requestTimeoutAtTime(mNextStepTime);
2184 }
2185 }
2186}
2187
2188void VibratorInputMapper::nextStep() {
2189 mIndex += 1;
2190 if (size_t(mIndex) >= mPatternSize) {
2191 if (mRepeat < 0) {
2192 // We are done.
2193 stopVibrating();
2194 return;
2195 }
2196 mIndex = mRepeat;
2197 }
2198
2199 bool vibratorOn = mIndex & 1;
2200 nsecs_t duration = mPattern[mIndex];
2201 if (vibratorOn) {
2202#if DEBUG_VIBRATOR
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07002203 ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002204#endif
2205 getEventHub()->vibrate(getDeviceId(), duration);
2206 } else {
2207#if DEBUG_VIBRATOR
2208 ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
2209#endif
2210 getEventHub()->cancelVibrate(getDeviceId());
2211 }
2212 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
2213 mNextStepTime = now + duration;
2214 getContext()->requestTimeoutAtTime(mNextStepTime);
2215#if DEBUG_VIBRATOR
2216 ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
2217#endif
2218}
2219
2220void VibratorInputMapper::stopVibrating() {
2221 mVibrating = false;
2222#if DEBUG_VIBRATOR
2223 ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
2224#endif
2225 getEventHub()->cancelVibrate(getDeviceId());
2226}
2227
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002228void VibratorInputMapper::dump(std::string& dump) {
2229 dump += INDENT2 "Vibrator Input Mapper:\n";
2230 dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002231}
2232
2233
2234// --- KeyboardInputMapper ---
2235
2236KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
2237 uint32_t source, int32_t keyboardType) :
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002238 InputMapper(device), mSource(source), mKeyboardType(keyboardType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002239}
2240
2241KeyboardInputMapper::~KeyboardInputMapper() {
2242}
2243
2244uint32_t KeyboardInputMapper::getSources() {
2245 return mSource;
2246}
2247
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002248int32_t KeyboardInputMapper::getOrientation() {
2249 if (mViewport) {
2250 return mViewport->orientation;
2251 }
2252 return DISPLAY_ORIENTATION_0;
2253}
2254
2255int32_t KeyboardInputMapper::getDisplayId() {
2256 if (mViewport) {
2257 return mViewport->displayId;
2258 }
2259 return ADISPLAY_ID_NONE;
2260}
2261
Michael Wrightd02c5b62014-02-10 15:10:22 -08002262void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2263 InputMapper::populateDeviceInfo(info);
2264
2265 info->setKeyboardType(mKeyboardType);
2266 info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
2267}
2268
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002269void KeyboardInputMapper::dump(std::string& dump) {
2270 dump += INDENT2 "Keyboard Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002271 dumpParameters(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002272 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002273 dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002274 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
2275 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
2276 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002277}
2278
Arthur Hung2c9a3342019-07-23 14:18:59 +08002279std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
2280 nsecs_t when, const InputReaderConfiguration* config) {
2281 const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
2282 if (displayPort) {
2283 // Find the viewport that contains the same port
2284 return mDevice->getAssociatedViewport();
2285 }
2286
2287 // No associated display defined, try to find default display if orientationAware.
2288 if (mParameters.orientationAware) {
2289 return config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
2290 }
2291
2292 return std::nullopt;
2293}
2294
Michael Wrightd02c5b62014-02-10 15:10:22 -08002295void KeyboardInputMapper::configure(nsecs_t when,
2296 const InputReaderConfiguration* config, uint32_t changes) {
2297 InputMapper::configure(when, config, changes);
2298
2299 if (!changes) { // first time only
2300 // Configure basic parameters.
2301 configureParameters();
2302 }
2303
2304 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Arthur Hung2c9a3342019-07-23 14:18:59 +08002305 mViewport = findViewport(when, config);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002306 }
2307}
2308
Ivan Podogovb9afef32017-02-13 15:34:32 +00002309static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
2310 int32_t mapped = 0;
2311 if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
2312 for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
2313 if (stemKeyRotationMap[i][0] == keyCode) {
2314 stemKeyRotationMap[i][1] = mapped;
2315 return;
2316 }
2317 }
2318 }
2319}
2320
Michael Wrightd02c5b62014-02-10 15:10:22 -08002321void KeyboardInputMapper::configureParameters() {
2322 mParameters.orientationAware = false;
Ivan Podogovb9afef32017-02-13 15:34:32 +00002323 const PropertyMap& config = getDevice()->getConfiguration();
2324 config.tryGetProperty(String8("keyboard.orientationAware"),
Michael Wrightd02c5b62014-02-10 15:10:22 -08002325 mParameters.orientationAware);
2326
Michael Wrightd02c5b62014-02-10 15:10:22 -08002327 if (mParameters.orientationAware) {
Ivan Podogovb9afef32017-02-13 15:34:32 +00002328 mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
2329 mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
2330 mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
2331 mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
Michael Wrightd02c5b62014-02-10 15:10:22 -08002332 }
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002333
2334 mParameters.handlesKeyRepeat = false;
Ivan Podogovb9afef32017-02-13 15:34:32 +00002335 config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002336 mParameters.handlesKeyRepeat);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002337}
2338
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002339void KeyboardInputMapper::dumpParameters(std::string& dump) {
2340 dump += INDENT3 "Parameters:\n";
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002341 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002342 toString(mParameters.orientationAware));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002343 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n",
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002344 toString(mParameters.handlesKeyRepeat));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002345}
2346
2347void KeyboardInputMapper::reset(nsecs_t when) {
2348 mMetaState = AMETA_NONE;
2349 mDownTime = 0;
2350 mKeyDowns.clear();
2351 mCurrentHidUsage = 0;
2352
2353 resetLedState();
2354
2355 InputMapper::reset(when);
2356}
2357
2358void KeyboardInputMapper::process(const RawEvent* rawEvent) {
2359 switch (rawEvent->type) {
2360 case EV_KEY: {
2361 int32_t scanCode = rawEvent->code;
2362 int32_t usageCode = mCurrentHidUsage;
2363 mCurrentHidUsage = 0;
2364
2365 if (isKeyboardOrGamepadKey(scanCode)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002366 processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002367 }
2368 break;
2369 }
2370 case EV_MSC: {
2371 if (rawEvent->code == MSC_SCAN) {
2372 mCurrentHidUsage = rawEvent->value;
2373 }
2374 break;
2375 }
2376 case EV_SYN: {
2377 if (rawEvent->code == SYN_REPORT) {
2378 mCurrentHidUsage = 0;
2379 }
2380 }
2381 }
2382}
2383
2384bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
2385 return scanCode < BTN_MOUSE
2386 || scanCode >= KEY_OK
2387 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
2388 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
2389}
2390
Michael Wright58ba9882017-07-26 16:19:11 +01002391bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
2392 switch (keyCode) {
2393 case AKEYCODE_MEDIA_PLAY:
2394 case AKEYCODE_MEDIA_PAUSE:
2395 case AKEYCODE_MEDIA_PLAY_PAUSE:
2396 case AKEYCODE_MUTE:
2397 case AKEYCODE_HEADSETHOOK:
2398 case AKEYCODE_MEDIA_STOP:
2399 case AKEYCODE_MEDIA_NEXT:
2400 case AKEYCODE_MEDIA_PREVIOUS:
2401 case AKEYCODE_MEDIA_REWIND:
2402 case AKEYCODE_MEDIA_RECORD:
2403 case AKEYCODE_MEDIA_FAST_FORWARD:
2404 case AKEYCODE_MEDIA_SKIP_FORWARD:
2405 case AKEYCODE_MEDIA_SKIP_BACKWARD:
2406 case AKEYCODE_MEDIA_STEP_FORWARD:
2407 case AKEYCODE_MEDIA_STEP_BACKWARD:
2408 case AKEYCODE_MEDIA_AUDIO_TRACK:
2409 case AKEYCODE_VOLUME_UP:
2410 case AKEYCODE_VOLUME_DOWN:
2411 case AKEYCODE_VOLUME_MUTE:
2412 case AKEYCODE_TV_AUDIO_DESCRIPTION:
2413 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
2414 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
2415 return true;
2416 }
2417 return false;
2418}
2419
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002420void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
2421 int32_t usageCode) {
2422 int32_t keyCode;
2423 int32_t keyMetaState;
2424 uint32_t policyFlags;
2425
2426 if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
2427 &keyCode, &keyMetaState, &policyFlags)) {
2428 keyCode = AKEYCODE_UNKNOWN;
2429 keyMetaState = mMetaState;
2430 policyFlags = 0;
2431 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002432
2433 if (down) {
2434 // Rotate key codes according to orientation if needed.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002435 if (mParameters.orientationAware) {
2436 keyCode = rotateKeyCode(keyCode, getOrientation());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002437 }
2438
2439 // Add key down.
2440 ssize_t keyDownIndex = findKeyDown(scanCode);
2441 if (keyDownIndex >= 0) {
2442 // key repeat, be sure to use same keycode as before in case of rotation
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002443 keyCode = mKeyDowns[keyDownIndex].keyCode;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002444 } else {
2445 // key down
2446 if ((policyFlags & POLICY_FLAG_VIRTUAL)
2447 && mContext->shouldDropVirtualKey(when,
2448 getDevice(), keyCode, scanCode)) {
2449 return;
2450 }
Jeff Brownc9aa6282015-02-11 19:03:28 -08002451 if (policyFlags & POLICY_FLAG_GESTURE) {
2452 mDevice->cancelTouch(when);
2453 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002454
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002455 KeyDown keyDown;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002456 keyDown.keyCode = keyCode;
2457 keyDown.scanCode = scanCode;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002458 mKeyDowns.push_back(keyDown);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002459 }
2460
2461 mDownTime = when;
2462 } else {
2463 // Remove key down.
2464 ssize_t keyDownIndex = findKeyDown(scanCode);
2465 if (keyDownIndex >= 0) {
2466 // key up, be sure to use same keycode as before in case of rotation
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002467 keyCode = mKeyDowns[keyDownIndex].keyCode;
2468 mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002469 } else {
2470 // key was not actually down
2471 ALOGI("Dropping key up from device %s because the key was not down. "
2472 "keyCode=%d, scanCode=%d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002473 getDeviceName().c_str(), keyCode, scanCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002474 return;
2475 }
2476 }
2477
Andrii Kulian763a3a42016-03-08 10:46:16 -08002478 if (updateMetaStateIfNeeded(keyCode, down)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002479 // If global meta state changed send it along with the key.
2480 // If it has not changed then we'll use what keymap gave us,
2481 // since key replacement logic might temporarily reset a few
2482 // meta bits for given key.
Andrii Kulian763a3a42016-03-08 10:46:16 -08002483 keyMetaState = mMetaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002484 }
2485
2486 nsecs_t downTime = mDownTime;
2487
2488 // Key down on external an keyboard should wake the device.
2489 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
2490 // For internal keyboards, the key layout file should specify the policy flags for
2491 // each wake key individually.
2492 // TODO: Use the input device configuration to control this behavior more finely.
Michael Wright58ba9882017-07-26 16:19:11 +01002493 if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
Michael Wright872db4f2014-04-22 15:03:51 -07002494 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002495 }
2496
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002497 if (mParameters.handlesKeyRepeat) {
2498 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
2499 }
2500
Prabir Pradhan42611e02018-11-27 14:04:02 -08002501 NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
2502 getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002503 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002504 getListener()->notifyKey(&args);
2505}
2506
2507ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
2508 size_t n = mKeyDowns.size();
2509 for (size_t i = 0; i < n; i++) {
2510 if (mKeyDowns[i].scanCode == scanCode) {
2511 return i;
2512 }
2513 }
2514 return -1;
2515}
2516
2517int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
2518 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
2519}
2520
2521int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2522 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2523}
2524
2525bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2526 const int32_t* keyCodes, uint8_t* outFlags) {
2527 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
2528}
2529
2530int32_t KeyboardInputMapper::getMetaState() {
2531 return mMetaState;
2532}
2533
Andrii Kulian763a3a42016-03-08 10:46:16 -08002534void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
2535 updateMetaStateIfNeeded(keyCode, false);
2536}
2537
2538bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
2539 int32_t oldMetaState = mMetaState;
2540 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
2541 bool metaStateChanged = oldMetaState != newMetaState;
2542 if (metaStateChanged) {
2543 mMetaState = newMetaState;
2544 updateLedState(false);
2545
2546 getContext()->updateGlobalMetaState();
2547 }
2548
2549 return metaStateChanged;
2550}
2551
Michael Wrightd02c5b62014-02-10 15:10:22 -08002552void KeyboardInputMapper::resetLedState() {
2553 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
2554 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
2555 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
2556
2557 updateLedState(true);
2558}
2559
2560void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
2561 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
2562 ledState.on = false;
2563}
2564
2565void KeyboardInputMapper::updateLedState(bool reset) {
2566 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
2567 AMETA_CAPS_LOCK_ON, reset);
2568 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
2569 AMETA_NUM_LOCK_ON, reset);
2570 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
2571 AMETA_SCROLL_LOCK_ON, reset);
2572}
2573
2574void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
2575 int32_t led, int32_t modifier, bool reset) {
2576 if (ledState.avail) {
2577 bool desiredState = (mMetaState & modifier) != 0;
2578 if (reset || ledState.on != desiredState) {
2579 getEventHub()->setLedState(getDeviceId(), led, desiredState);
2580 ledState.on = desiredState;
2581 }
2582 }
2583}
2584
Arthur Hung2c9a3342019-07-23 14:18:59 +08002585std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() {
2586 if (mViewport) {
2587 return std::make_optional(mViewport->displayId);
2588 }
2589 return std::nullopt;
2590}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002591
2592// --- CursorInputMapper ---
2593
2594CursorInputMapper::CursorInputMapper(InputDevice* device) :
2595 InputMapper(device) {
2596}
2597
2598CursorInputMapper::~CursorInputMapper() {
2599}
2600
2601uint32_t CursorInputMapper::getSources() {
2602 return mSource;
2603}
2604
2605void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2606 InputMapper::populateDeviceInfo(info);
2607
2608 if (mParameters.mode == Parameters::MODE_POINTER) {
2609 float minX, minY, maxX, maxY;
2610 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
2611 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
2612 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
2613 }
2614 } else {
2615 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
2616 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
2617 }
2618 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2619
2620 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2621 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2622 }
2623 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2624 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2625 }
2626}
2627
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002628void CursorInputMapper::dump(std::string& dump) {
2629 dump += INDENT2 "Cursor Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002630 dumpParameters(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002631 dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
2632 dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
2633 dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
2634 dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
2635 dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002636 toString(mCursorScrollAccumulator.haveRelativeVWheel()));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002637 dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002638 toString(mCursorScrollAccumulator.haveRelativeHWheel()));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002639 dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
2640 dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
2641 dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
2642 dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
2643 dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
2644 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002645}
2646
2647void CursorInputMapper::configure(nsecs_t when,
2648 const InputReaderConfiguration* config, uint32_t changes) {
2649 InputMapper::configure(when, config, changes);
2650
2651 if (!changes) { // first time only
2652 mCursorScrollAccumulator.configure(getDevice());
2653
2654 // Configure basic parameters.
2655 configureParameters();
2656
2657 // Configure device mode.
2658 switch (mParameters.mode) {
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002659 case Parameters::MODE_POINTER_RELATIVE:
2660 // Should not happen during first time configuration.
2661 ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
2662 mParameters.mode = Parameters::MODE_POINTER;
Chih-Hung Hsieh8d1b40a2018-10-19 11:38:06 -07002663 [[fallthrough]];
Michael Wrightd02c5b62014-02-10 15:10:22 -08002664 case Parameters::MODE_POINTER:
2665 mSource = AINPUT_SOURCE_MOUSE;
2666 mXPrecision = 1.0f;
2667 mYPrecision = 1.0f;
2668 mXScale = 1.0f;
2669 mYScale = 1.0f;
2670 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2671 break;
2672 case Parameters::MODE_NAVIGATION:
2673 mSource = AINPUT_SOURCE_TRACKBALL;
2674 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2675 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2676 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2677 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2678 break;
2679 }
2680
2681 mVWheelScale = 1.0f;
2682 mHWheelScale = 1.0f;
2683 }
2684
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002685 if ((!changes && config->pointerCapture)
2686 || (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
2687 if (config->pointerCapture) {
2688 if (mParameters.mode == Parameters::MODE_POINTER) {
2689 mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
2690 mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
2691 // Keep PointerController around in order to preserve the pointer position.
2692 mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2693 } else {
2694 ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
2695 }
2696 } else {
2697 if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
2698 mParameters.mode = Parameters::MODE_POINTER;
2699 mSource = AINPUT_SOURCE_MOUSE;
2700 } else {
2701 ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
2702 }
2703 }
2704 bumpGeneration();
2705 if (changes) {
2706 getDevice()->notifyReset(when);
2707 }
2708 }
2709
Michael Wrightd02c5b62014-02-10 15:10:22 -08002710 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2711 mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
2712 mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
2713 mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
2714 }
2715
2716 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002717 mOrientation = DISPLAY_ORIENTATION_0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002718 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07002719 std::optional<DisplayViewport> internalViewport =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07002720 config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07002721 if (internalViewport) {
2722 mOrientation = internalViewport->orientation;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002723 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002724 }
Arthur Hungc7ad2d02018-12-18 17:41:29 +08002725
2726 // Update the PointerController if viewports changed.
Arthur Hungc23540e2018-11-29 20:42:11 +08002727 if (mParameters.mode == Parameters::MODE_POINTER) {
Arthur Hungc7ad2d02018-12-18 17:41:29 +08002728 getPolicy()->obtainPointerController(getDeviceId());
2729 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002730 bumpGeneration();
2731 }
2732}
2733
2734void CursorInputMapper::configureParameters() {
2735 mParameters.mode = Parameters::MODE_POINTER;
2736 String8 cursorModeString;
2737 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
2738 if (cursorModeString == "navigation") {
2739 mParameters.mode = Parameters::MODE_NAVIGATION;
2740 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
2741 ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
2742 }
2743 }
2744
2745 mParameters.orientationAware = false;
2746 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
2747 mParameters.orientationAware);
2748
2749 mParameters.hasAssociatedDisplay = false;
2750 if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
2751 mParameters.hasAssociatedDisplay = true;
2752 }
2753}
2754
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002755void CursorInputMapper::dumpParameters(std::string& dump) {
2756 dump += INDENT3 "Parameters:\n";
2757 dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002758 toString(mParameters.hasAssociatedDisplay));
2759
2760 switch (mParameters.mode) {
2761 case Parameters::MODE_POINTER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002762 dump += INDENT4 "Mode: pointer\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002763 break;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002764 case Parameters::MODE_POINTER_RELATIVE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002765 dump += INDENT4 "Mode: relative pointer\n";
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002766 break;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002767 case Parameters::MODE_NAVIGATION:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002768 dump += INDENT4 "Mode: navigation\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002769 break;
2770 default:
2771 ALOG_ASSERT(false);
2772 }
2773
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002774 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002775 toString(mParameters.orientationAware));
2776}
2777
2778void CursorInputMapper::reset(nsecs_t when) {
2779 mButtonState = 0;
2780 mDownTime = 0;
2781
2782 mPointerVelocityControl.reset();
2783 mWheelXVelocityControl.reset();
2784 mWheelYVelocityControl.reset();
2785
2786 mCursorButtonAccumulator.reset(getDevice());
2787 mCursorMotionAccumulator.reset(getDevice());
2788 mCursorScrollAccumulator.reset(getDevice());
2789
2790 InputMapper::reset(when);
2791}
2792
2793void CursorInputMapper::process(const RawEvent* rawEvent) {
2794 mCursorButtonAccumulator.process(rawEvent);
2795 mCursorMotionAccumulator.process(rawEvent);
2796 mCursorScrollAccumulator.process(rawEvent);
2797
2798 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
2799 sync(rawEvent->when);
2800 }
2801}
2802
2803void CursorInputMapper::sync(nsecs_t when) {
2804 int32_t lastButtonState = mButtonState;
2805 int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
2806 mButtonState = currentButtonState;
2807
2808 bool wasDown = isPointerDown(lastButtonState);
2809 bool down = isPointerDown(currentButtonState);
2810 bool downChanged;
2811 if (!wasDown && down) {
2812 mDownTime = when;
2813 downChanged = true;
2814 } else if (wasDown && !down) {
2815 downChanged = true;
2816 } else {
2817 downChanged = false;
2818 }
2819 nsecs_t downTime = mDownTime;
2820 bool buttonsChanged = currentButtonState != lastButtonState;
Michael Wright7b159c92015-05-14 14:48:03 +01002821 int32_t buttonsPressed = currentButtonState & ~lastButtonState;
2822 int32_t buttonsReleased = lastButtonState & ~currentButtonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002823
2824 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
2825 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
2826 bool moved = deltaX != 0 || deltaY != 0;
2827
2828 // Rotate delta according to orientation if needed.
2829 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
2830 && (deltaX != 0.0f || deltaY != 0.0f)) {
2831 rotateDelta(mOrientation, &deltaX, &deltaY);
2832 }
2833
2834 // Move the pointer.
2835 PointerProperties pointerProperties;
2836 pointerProperties.clear();
2837 pointerProperties.id = 0;
2838 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
2839
2840 PointerCoords pointerCoords;
2841 pointerCoords.clear();
2842
2843 float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
2844 float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
2845 bool scrolled = vscroll != 0 || hscroll != 0;
2846
Yi Kong9b14ac62018-07-17 13:48:38 -07002847 mWheelYVelocityControl.move(when, nullptr, &vscroll);
2848 mWheelXVelocityControl.move(when, &hscroll, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002849
2850 mPointerVelocityControl.move(when, &deltaX, &deltaY);
2851
2852 int32_t displayId;
Garfield Tan00f511d2019-06-12 16:55:40 -07002853 float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
2854 float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002855 if (mSource == AINPUT_SOURCE_MOUSE) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002856 if (moved || scrolled || buttonsChanged) {
2857 mPointerController->setPresentation(
2858 PointerControllerInterface::PRESENTATION_POINTER);
2859
2860 if (moved) {
2861 mPointerController->move(deltaX, deltaY);
2862 }
2863
2864 if (buttonsChanged) {
2865 mPointerController->setButtonState(currentButtonState);
2866 }
2867
2868 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2869 }
2870
Garfield Tan00f511d2019-06-12 16:55:40 -07002871 mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
2872 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
2873 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
Jun Mukaifa1706a2015-12-03 01:14:46 -08002874 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
2875 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08002876 displayId = mPointerController->getDisplayId();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002877 } else {
2878 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
2879 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
2880 displayId = ADISPLAY_ID_NONE;
2881 }
2882
2883 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
2884
2885 // Moving an external trackball or mouse should wake the device.
2886 // We don't do this for internal cursor devices to prevent them from waking up
2887 // the device in your pocket.
2888 // TODO: Use the input device configuration to control this behavior more finely.
2889 uint32_t policyFlags = 0;
2890 if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
Michael Wright872db4f2014-04-22 15:03:51 -07002891 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002892 }
2893
2894 // Synthesize key down from buttons if needed.
2895 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002896 displayId, policyFlags, lastButtonState, currentButtonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002897
2898 // Send motion event.
2899 if (downChanged || moved || scrolled || buttonsChanged) {
2900 int32_t metaState = mContext->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01002901 int32_t buttonState = lastButtonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002902 int32_t motionEventAction;
2903 if (downChanged) {
2904 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002905 } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002906 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2907 } else {
2908 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
2909 }
2910
Michael Wright7b159c92015-05-14 14:48:03 +01002911 if (buttonsReleased) {
2912 BitSet32 released(buttonsReleased);
2913 while (!released.isEmpty()) {
2914 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
2915 buttonState &= ~actionButton;
Prabir Pradhan42611e02018-11-27 14:04:02 -08002916 NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07002917 mSource, displayId, policyFlags,
2918 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
2919 metaState, buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002920 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002921 &pointerCoords, mXPrecision, mYPrecision,
2922 xCursorPosition, yCursorPosition, downTime,
2923 /* videoFrames */ {});
Michael Wright7b159c92015-05-14 14:48:03 +01002924 getListener()->notifyMotion(&releaseArgs);
2925 }
2926 }
2927
Prabir Pradhan42611e02018-11-27 14:04:02 -08002928 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
Garfield Tan00f511d2019-06-12 16:55:40 -07002929 displayId, policyFlags, motionEventAction, 0, 0, metaState,
2930 currentButtonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002931 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
Garfield Tan00f511d2019-06-12 16:55:40 -07002932 mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
2933 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002934 getListener()->notifyMotion(&args);
2935
Michael Wright7b159c92015-05-14 14:48:03 +01002936 if (buttonsPressed) {
2937 BitSet32 pressed(buttonsPressed);
2938 while (!pressed.isEmpty()) {
2939 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
2940 buttonState |= actionButton;
Prabir Pradhan42611e02018-11-27 14:04:02 -08002941 NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07002942 mSource, displayId, policyFlags,
2943 AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
2944 metaState, buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002945 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002946 &pointerCoords, mXPrecision, mYPrecision,
2947 xCursorPosition, yCursorPosition, downTime,
2948 /* videoFrames */ {});
Michael Wright7b159c92015-05-14 14:48:03 +01002949 getListener()->notifyMotion(&pressArgs);
2950 }
2951 }
2952
2953 ALOG_ASSERT(buttonState == currentButtonState);
2954
Michael Wrightd02c5b62014-02-10 15:10:22 -08002955 // Send hover move after UP to tell the application that the mouse is hovering now.
2956 if (motionEventAction == AMOTION_EVENT_ACTION_UP
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002957 && (mSource == AINPUT_SOURCE_MOUSE)) {
Garfield Tan00f511d2019-06-12 16:55:40 -07002958 NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
2959 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
2960 0, metaState, currentButtonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002961 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002962 &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002963 yCursorPosition, downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002964 getListener()->notifyMotion(&hoverArgs);
2965 }
2966
2967 // Send scroll events.
2968 if (scrolled) {
2969 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2970 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2971
Prabir Pradhan42611e02018-11-27 14:04:02 -08002972 NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07002973 mSource, displayId, policyFlags,
2974 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
2975 currentButtonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002976 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002977 &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002978 yCursorPosition, downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002979 getListener()->notifyMotion(&scrollArgs);
2980 }
2981 }
2982
2983 // Synthesize key up from buttons if needed.
2984 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002985 displayId, policyFlags, lastButtonState, currentButtonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002986
2987 mCursorMotionAccumulator.finishSync();
2988 mCursorScrollAccumulator.finishSync();
2989}
2990
2991int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2992 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2993 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2994 } else {
2995 return AKEY_STATE_UNKNOWN;
2996 }
2997}
2998
2999void CursorInputMapper::fadePointer() {
Yi Kong9b14ac62018-07-17 13:48:38 -07003000 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003001 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3002 }
3003}
3004
Arthur Hung2c9a3342019-07-23 14:18:59 +08003005std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() {
Arthur Hungc23540e2018-11-29 20:42:11 +08003006 if (mParameters.hasAssociatedDisplay) {
3007 if (mParameters.mode == Parameters::MODE_POINTER) {
3008 return std::make_optional(mPointerController->getDisplayId());
3009 } else {
3010 // If the device is orientationAware and not a mouse,
3011 // it expects to dispatch events to any display
3012 return std::make_optional(ADISPLAY_ID_NONE);
3013 }
3014 }
3015 return std::nullopt;
3016}
3017
Prashant Malani1941ff52015-08-11 18:29:28 -07003018// --- RotaryEncoderInputMapper ---
3019
3020RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
Ivan Podogovad437252016-09-29 16:29:55 +01003021 InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
Prashant Malani1941ff52015-08-11 18:29:28 -07003022 mSource = AINPUT_SOURCE_ROTARY_ENCODER;
3023}
3024
3025RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
3026}
3027
3028uint32_t RotaryEncoderInputMapper::getSources() {
3029 return mSource;
3030}
3031
3032void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3033 InputMapper::populateDeviceInfo(info);
3034
3035 if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
Prashant Malanidae627a2016-01-11 17:08:18 -08003036 float res = 0.0f;
3037 if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
3038 ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
3039 }
3040 if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
3041 mScalingFactor)) {
3042 ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
3043 "default to 1.0!\n");
3044 mScalingFactor = 1.0f;
3045 }
3046 info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3047 res * mScalingFactor);
Prashant Malani1941ff52015-08-11 18:29:28 -07003048 }
3049}
3050
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003051void RotaryEncoderInputMapper::dump(std::string& dump) {
3052 dump += INDENT2 "Rotary Encoder Input Mapper:\n";
3053 dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
Prashant Malani1941ff52015-08-11 18:29:28 -07003054 toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
3055}
3056
3057void RotaryEncoderInputMapper::configure(nsecs_t when,
3058 const InputReaderConfiguration* config, uint32_t changes) {
3059 InputMapper::configure(when, config, changes);
3060 if (!changes) {
3061 mRotaryEncoderScrollAccumulator.configure(getDevice());
3062 }
Siarhei Vishniakoud00e7872018-08-09 09:22:45 -07003063 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003064 std::optional<DisplayViewport> internalViewport =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003065 config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07003066 if (internalViewport) {
3067 mOrientation = internalViewport->orientation;
Ivan Podogovad437252016-09-29 16:29:55 +01003068 } else {
3069 mOrientation = DISPLAY_ORIENTATION_0;
3070 }
3071 }
Prashant Malani1941ff52015-08-11 18:29:28 -07003072}
3073
3074void RotaryEncoderInputMapper::reset(nsecs_t when) {
3075 mRotaryEncoderScrollAccumulator.reset(getDevice());
3076
3077 InputMapper::reset(when);
3078}
3079
3080void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
3081 mRotaryEncoderScrollAccumulator.process(rawEvent);
3082
3083 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
3084 sync(rawEvent->when);
3085 }
3086}
3087
3088void RotaryEncoderInputMapper::sync(nsecs_t when) {
3089 PointerCoords pointerCoords;
3090 pointerCoords.clear();
3091
3092 PointerProperties pointerProperties;
3093 pointerProperties.clear();
3094 pointerProperties.id = 0;
3095 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
3096
3097 float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
3098 bool scrolled = scroll != 0;
3099
3100 // This is not a pointer, so it's not associated with a display.
3101 int32_t displayId = ADISPLAY_ID_NONE;
3102
3103 // Moving the rotary encoder should wake the device (if specified).
3104 uint32_t policyFlags = 0;
3105 if (scrolled && getDevice()->isExternal()) {
3106 policyFlags |= POLICY_FLAG_WAKE;
3107 }
3108
Ivan Podogovad437252016-09-29 16:29:55 +01003109 if (mOrientation == DISPLAY_ORIENTATION_180) {
3110 scroll = -scroll;
3111 }
3112
Prashant Malani1941ff52015-08-11 18:29:28 -07003113 // Send motion event.
3114 if (scrolled) {
3115 int32_t metaState = mContext->getGlobalMetaState();
Prashant Malanidae627a2016-01-11 17:08:18 -08003116 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
Prashant Malani1941ff52015-08-11 18:29:28 -07003117
Garfield Tan00f511d2019-06-12 16:55:40 -07003118 NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
3119 displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
3120 metaState, /* buttonState */ 0, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07003121 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
3122 &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Garfield Tan00f511d2019-06-12 16:55:40 -07003123 AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
Prashant Malani1941ff52015-08-11 18:29:28 -07003124 getListener()->notifyMotion(&scrollArgs);
3125 }
3126
3127 mRotaryEncoderScrollAccumulator.finishSync();
3128}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003129
3130// --- TouchInputMapper ---
3131
3132TouchInputMapper::TouchInputMapper(InputDevice* device) :
3133 InputMapper(device),
3134 mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
3135 mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
Michael Wright358bcc72018-08-21 04:01:07 +01003136 mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003137 mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
3138}
3139
3140TouchInputMapper::~TouchInputMapper() {
3141}
3142
3143uint32_t TouchInputMapper::getSources() {
3144 return mSource;
3145}
3146
3147void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3148 InputMapper::populateDeviceInfo(info);
3149
3150 if (mDeviceMode != DEVICE_MODE_DISABLED) {
3151 info->addMotionRange(mOrientedRanges.x);
3152 info->addMotionRange(mOrientedRanges.y);
3153 info->addMotionRange(mOrientedRanges.pressure);
3154
3155 if (mOrientedRanges.haveSize) {
3156 info->addMotionRange(mOrientedRanges.size);
3157 }
3158
3159 if (mOrientedRanges.haveTouchSize) {
3160 info->addMotionRange(mOrientedRanges.touchMajor);
3161 info->addMotionRange(mOrientedRanges.touchMinor);
3162 }
3163
3164 if (mOrientedRanges.haveToolSize) {
3165 info->addMotionRange(mOrientedRanges.toolMajor);
3166 info->addMotionRange(mOrientedRanges.toolMinor);
3167 }
3168
3169 if (mOrientedRanges.haveOrientation) {
3170 info->addMotionRange(mOrientedRanges.orientation);
3171 }
3172
3173 if (mOrientedRanges.haveDistance) {
3174 info->addMotionRange(mOrientedRanges.distance);
3175 }
3176
3177 if (mOrientedRanges.haveTilt) {
3178 info->addMotionRange(mOrientedRanges.tilt);
3179 }
3180
3181 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
3182 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3183 0.0f);
3184 }
3185 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
3186 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3187 0.0f);
3188 }
3189 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
3190 const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
3191 const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
3192 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
3193 x.fuzz, x.resolution);
3194 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
3195 y.fuzz, y.resolution);
3196 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
3197 x.fuzz, x.resolution);
3198 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
3199 y.fuzz, y.resolution);
3200 }
3201 info->setButtonUnderPad(mParameters.hasButtonUnderPad);
3202 }
3203}
3204
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003205void TouchInputMapper::dump(std::string& dump) {
3206 dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003207 dumpParameters(dump);
3208 dumpVirtualKeys(dump);
3209 dumpRawPointerAxes(dump);
3210 dumpCalibration(dump);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07003211 dumpAffineTransformation(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003212 dumpSurface(dump);
3213
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003214 dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
3215 dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
3216 dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
3217 dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
3218 dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
3219 dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
3220 dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
3221 dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
3222 dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
3223 dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
3224 dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
3225 dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
3226 dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
3227 dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
3228 dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
3229 dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
3230 dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003231
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003232 dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
3233 dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07003234 mLastRawState.rawPointerData.pointerCount);
3235 for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
3236 const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003237 dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003238 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
3239 "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
3240 "toolType=%d, isHovering=%s\n", i,
3241 pointer.id, pointer.x, pointer.y, pointer.pressure,
3242 pointer.touchMajor, pointer.touchMinor,
3243 pointer.toolMajor, pointer.toolMinor,
3244 pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
3245 pointer.toolType, toString(pointer.isHovering));
3246 }
3247
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003248 dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState);
3249 dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07003250 mLastCookedState.cookedPointerData.pointerCount);
3251 for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
3252 const PointerProperties& pointerProperties =
3253 mLastCookedState.cookedPointerData.pointerProperties[i];
3254 const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003255 dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003256 "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
3257 "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
3258 "toolType=%d, isHovering=%s\n", i,
3259 pointerProperties.id,
3260 pointerCoords.getX(),
3261 pointerCoords.getY(),
3262 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
3263 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
3264 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
3265 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
3266 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
3267 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
3268 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
3269 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
3270 pointerProperties.toolType,
Michael Wright842500e2015-03-13 17:32:02 -07003271 toString(mLastCookedState.cookedPointerData.isHovering(i)));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003272 }
3273
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003274 dump += INDENT3 "Stylus Fusion:\n";
3275 dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
Michael Wright842500e2015-03-13 17:32:02 -07003276 toString(mExternalStylusConnected));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003277 dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
3278 dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
Michael Wright43fd19f2015-04-21 19:02:58 +01003279 mExternalStylusFusionTimeout);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003280 dump += INDENT3 "External Stylus State:\n";
Michael Wright842500e2015-03-13 17:32:02 -07003281 dumpStylusState(dump, mExternalStylusState);
3282
Michael Wrightd02c5b62014-02-10 15:10:22 -08003283 if (mDeviceMode == DEVICE_MODE_POINTER) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003284 dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
3285 dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003286 mPointerXMovementScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003287 dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003288 mPointerYMovementScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003289 dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003290 mPointerXZoomScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003291 dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003292 mPointerYZoomScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003293 dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003294 mPointerGestureMaxSwipeWidth);
3295 }
3296}
3297
Santos Cordonfa5cf462017-04-05 10:37:00 -07003298const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
3299 switch (deviceMode) {
3300 case DEVICE_MODE_DISABLED:
3301 return "disabled";
3302 case DEVICE_MODE_DIRECT:
3303 return "direct";
3304 case DEVICE_MODE_UNSCALED:
3305 return "unscaled";
3306 case DEVICE_MODE_NAVIGATION:
3307 return "navigation";
3308 case DEVICE_MODE_POINTER:
3309 return "pointer";
3310 }
3311 return "unknown";
3312}
3313
Michael Wrightd02c5b62014-02-10 15:10:22 -08003314void TouchInputMapper::configure(nsecs_t when,
3315 const InputReaderConfiguration* config, uint32_t changes) {
3316 InputMapper::configure(when, config, changes);
3317
3318 mConfig = *config;
3319
3320 if (!changes) { // first time only
3321 // Configure basic parameters.
3322 configureParameters();
3323
3324 // Configure common accumulators.
3325 mCursorScrollAccumulator.configure(getDevice());
3326 mTouchButtonAccumulator.configure(getDevice());
3327
3328 // Configure absolute axis information.
3329 configureRawPointerAxes();
3330
3331 // Prepare input device calibration.
3332 parseCalibration();
3333 resolveCalibration();
3334 }
3335
Michael Wright842500e2015-03-13 17:32:02 -07003336 if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
Jason Gerecke12d6baa2014-01-27 18:34:20 -08003337 // Update location calibration to reflect current settings
3338 updateAffineTransformation();
3339 }
3340
Michael Wrightd02c5b62014-02-10 15:10:22 -08003341 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
3342 // Update pointer speed.
3343 mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
3344 mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
3345 mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
3346 }
3347
3348 bool resetNeeded = false;
3349 if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
3350 | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
Michael Wright842500e2015-03-13 17:32:02 -07003351 | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
3352 | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003353 // Configure device sources, surface dimensions, orientation and
3354 // scaling factors.
3355 configureSurface(when, &resetNeeded);
3356 }
3357
3358 if (changes && resetNeeded) {
3359 // Send reset, unless this is the first time the device has been configured,
3360 // in which case the reader will call reset itself after all mappers are ready.
3361 getDevice()->notifyReset(when);
3362 }
3363}
3364
Michael Wright842500e2015-03-13 17:32:02 -07003365void TouchInputMapper::resolveExternalStylusPresence() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003366 std::vector<InputDeviceInfo> devices;
Michael Wright842500e2015-03-13 17:32:02 -07003367 mContext->getExternalStylusDevices(devices);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003368 mExternalStylusConnected = !devices.empty();
Michael Wright842500e2015-03-13 17:32:02 -07003369
3370 if (!mExternalStylusConnected) {
3371 resetExternalStylus();
3372 }
3373}
3374
Michael Wrightd02c5b62014-02-10 15:10:22 -08003375void TouchInputMapper::configureParameters() {
3376 // Use the pointer presentation mode for devices that do not support distinct
3377 // multitouch. The spot-based presentation relies on being able to accurately
3378 // locate two or more fingers on the touch pad.
3379 mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003380 ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003381
3382 String8 gestureModeString;
3383 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
3384 gestureModeString)) {
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003385 if (gestureModeString == "single-touch") {
3386 mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
3387 } else if (gestureModeString == "multi-touch") {
3388 mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003389 } else if (gestureModeString != "default") {
3390 ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
3391 }
3392 }
3393
3394 if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
3395 // The device is a touch screen.
3396 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3397 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
3398 // The device is a pointing device like a track pad.
3399 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3400 } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
3401 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
3402 // The device is a cursor device with a touch pad attached.
3403 // By default don't use the touch pad to move the pointer.
3404 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
3405 } else {
3406 // The device is a touch pad of unknown purpose.
3407 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3408 }
3409
3410 mParameters.hasButtonUnderPad=
3411 getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
3412
3413 String8 deviceTypeString;
3414 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
3415 deviceTypeString)) {
3416 if (deviceTypeString == "touchScreen") {
3417 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3418 } else if (deviceTypeString == "touchPad") {
3419 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
3420 } else if (deviceTypeString == "touchNavigation") {
3421 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
3422 } else if (deviceTypeString == "pointer") {
3423 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3424 } else if (deviceTypeString != "default") {
3425 ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
3426 }
3427 }
3428
3429 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3430 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
3431 mParameters.orientationAware);
3432
3433 mParameters.hasAssociatedDisplay = false;
3434 mParameters.associatedDisplayIsExternal = false;
3435 if (mParameters.orientationAware
3436 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3437 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
3438 mParameters.hasAssociatedDisplay = true;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003439 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
3440 mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003441 String8 uniqueDisplayId;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003442 getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003443 uniqueDisplayId);
3444 mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
Santos Cordonfa5cf462017-04-05 10:37:00 -07003445 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003446 }
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003447 if (getDevice()->getAssociatedDisplayPort()) {
3448 mParameters.hasAssociatedDisplay = true;
3449 }
Jeff Brownc5e24422014-02-26 18:48:51 -08003450
3451 // Initial downs on external touch devices should wake the device.
3452 // Normally we don't do this for internal touch screens to prevent them from waking
3453 // up in your pocket but you can enable it using the input device configuration.
3454 mParameters.wake = getDevice()->isExternal();
3455 getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"),
3456 mParameters.wake);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003457}
3458
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003459void TouchInputMapper::dumpParameters(std::string& dump) {
3460 dump += INDENT3 "Parameters:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003461
3462 switch (mParameters.gestureMode) {
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003463 case Parameters::GESTURE_MODE_SINGLE_TOUCH:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003464 dump += INDENT4 "GestureMode: single-touch\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003465 break;
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003466 case Parameters::GESTURE_MODE_MULTI_TOUCH:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003467 dump += INDENT4 "GestureMode: multi-touch\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003468 break;
3469 default:
3470 assert(false);
3471 }
3472
3473 switch (mParameters.deviceType) {
3474 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003475 dump += INDENT4 "DeviceType: touchScreen\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003476 break;
3477 case Parameters::DEVICE_TYPE_TOUCH_PAD:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003478 dump += INDENT4 "DeviceType: touchPad\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003479 break;
3480 case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003481 dump += INDENT4 "DeviceType: touchNavigation\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003482 break;
3483 case Parameters::DEVICE_TYPE_POINTER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003484 dump += INDENT4 "DeviceType: pointer\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003485 break;
3486 default:
3487 ALOG_ASSERT(false);
3488 }
3489
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003490 dump += StringPrintf(
Santos Cordonfa5cf462017-04-05 10:37:00 -07003491 INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, displayId='%s'\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003492 toString(mParameters.hasAssociatedDisplay),
Santos Cordonfa5cf462017-04-05 10:37:00 -07003493 toString(mParameters.associatedDisplayIsExternal),
3494 mParameters.uniqueDisplayId.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003495 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003496 toString(mParameters.orientationAware));
3497}
3498
3499void TouchInputMapper::configureRawPointerAxes() {
3500 mRawPointerAxes.clear();
3501}
3502
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003503void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
3504 dump += INDENT3 "Raw Touch Axes:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003505 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
3506 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
3507 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
3508 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
3509 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
3510 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
3511 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
3512 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
3513 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
3514 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
3515 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
3516 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
3517 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
3518}
3519
Michael Wright842500e2015-03-13 17:32:02 -07003520bool TouchInputMapper::hasExternalStylus() const {
3521 return mExternalStylusConnected;
3522}
3523
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003524/**
3525 * Determine which DisplayViewport to use.
3526 * 1. If display port is specified, return the matching viewport. If matching viewport not
3527 * found, then return.
3528 * 2. If a device has associated display, get the matching viewport by either unique id or by
3529 * the display type (internal or external).
3530 * 3. Otherwise, use a non-display viewport.
3531 */
3532std::optional<DisplayViewport> TouchInputMapper::findViewport() {
3533 if (mParameters.hasAssociatedDisplay) {
3534 const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
3535 if (displayPort) {
3536 // Find the viewport that contains the same port
Arthur Hung2c9a3342019-07-23 14:18:59 +08003537 return mDevice->getAssociatedViewport();
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003538 }
3539
Arthur Hung2c9a3342019-07-23 14:18:59 +08003540 // Check if uniqueDisplayId is specified in idc file.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003541 if (!mParameters.uniqueDisplayId.empty()) {
3542 return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
3543 }
3544
3545 ViewportType viewportTypeToUse;
3546 if (mParameters.associatedDisplayIsExternal) {
3547 viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
3548 } else {
3549 viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
3550 }
Arthur Hung41a712e2018-11-22 19:41:03 +08003551
3552 std::optional<DisplayViewport> viewport =
3553 mConfig.getDisplayViewportByType(viewportTypeToUse);
3554 if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
3555 ALOGW("Input device %s should be associated with external display, "
3556 "fallback to internal one for the external viewport is not found.",
3557 getDeviceName().c_str());
3558 viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
3559 }
3560
3561 return viewport;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003562 }
3563
Arthur Hung2c9a3342019-07-23 14:18:59 +08003564 // No associated display, return a non-display viewport.
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003565 DisplayViewport newViewport;
3566 // Raw width and height in the natural orientation.
3567 int32_t rawWidth = mRawPointerAxes.getRawWidth();
3568 int32_t rawHeight = mRawPointerAxes.getRawHeight();
3569 newViewport.setNonDisplayViewport(rawWidth, rawHeight);
3570 return std::make_optional(newViewport);
3571}
3572
Michael Wrightd02c5b62014-02-10 15:10:22 -08003573void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
3574 int32_t oldDeviceMode = mDeviceMode;
3575
Michael Wright842500e2015-03-13 17:32:02 -07003576 resolveExternalStylusPresence();
3577
Michael Wrightd02c5b62014-02-10 15:10:22 -08003578 // Determine device mode.
3579 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
3580 && mConfig.pointerGesturesEnabled) {
3581 mSource = AINPUT_SOURCE_MOUSE;
3582 mDeviceMode = DEVICE_MODE_POINTER;
3583 if (hasStylus()) {
3584 mSource |= AINPUT_SOURCE_STYLUS;
3585 }
3586 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3587 && mParameters.hasAssociatedDisplay) {
3588 mSource = AINPUT_SOURCE_TOUCHSCREEN;
3589 mDeviceMode = DEVICE_MODE_DIRECT;
Michael Wright2f78b682015-06-12 15:25:08 +01003590 if (hasStylus()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003591 mSource |= AINPUT_SOURCE_STYLUS;
3592 }
Michael Wright2f78b682015-06-12 15:25:08 +01003593 if (hasExternalStylus()) {
3594 mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
3595 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003596 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
3597 mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
3598 mDeviceMode = DEVICE_MODE_NAVIGATION;
3599 } else {
3600 mSource = AINPUT_SOURCE_TOUCHPAD;
3601 mDeviceMode = DEVICE_MODE_UNSCALED;
3602 }
3603
3604 // Ensure we have valid X and Y axes.
3605 if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003606 ALOGW("Touch device '%s' did not report support for X or Y axis! "
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003607 "The device will be inoperable.", getDeviceName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003608 mDeviceMode = DEVICE_MODE_DISABLED;
3609 return;
3610 }
3611
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003612 // Get associated display dimensions.
3613 std::optional<DisplayViewport> newViewport = findViewport();
3614 if (!newViewport) {
3615 ALOGI("Touch device '%s' could not query the properties of its associated "
3616 "display. The device will be inoperable until the display size "
3617 "becomes available.",
3618 getDeviceName().c_str());
3619 mDeviceMode = DEVICE_MODE_DISABLED;
3620 return;
3621 }
3622
Michael Wrightd02c5b62014-02-10 15:10:22 -08003623 // Raw width and height in the natural orientation.
Siarhei Vishniakou26e34d92018-11-12 13:51:26 -08003624 int32_t rawWidth = mRawPointerAxes.getRawWidth();
3625 int32_t rawHeight = mRawPointerAxes.getRawHeight();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003626
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003627 bool viewportChanged = mViewport != *newViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003628 if (viewportChanged) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003629 mViewport = *newViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003630
3631 if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
3632 // Convert rotated viewport to natural surface coordinates.
3633 int32_t naturalLogicalWidth, naturalLogicalHeight;
3634 int32_t naturalPhysicalWidth, naturalPhysicalHeight;
3635 int32_t naturalPhysicalLeft, naturalPhysicalTop;
3636 int32_t naturalDeviceWidth, naturalDeviceHeight;
3637 switch (mViewport.orientation) {
3638 case DISPLAY_ORIENTATION_90:
3639 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3640 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3641 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3642 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3643 naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
3644 naturalPhysicalTop = mViewport.physicalLeft;
3645 naturalDeviceWidth = mViewport.deviceHeight;
3646 naturalDeviceHeight = mViewport.deviceWidth;
3647 break;
3648 case DISPLAY_ORIENTATION_180:
3649 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3650 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3651 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3652 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3653 naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
3654 naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
3655 naturalDeviceWidth = mViewport.deviceWidth;
3656 naturalDeviceHeight = mViewport.deviceHeight;
3657 break;
3658 case DISPLAY_ORIENTATION_270:
3659 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3660 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3661 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3662 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3663 naturalPhysicalLeft = mViewport.physicalTop;
3664 naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
3665 naturalDeviceWidth = mViewport.deviceHeight;
3666 naturalDeviceHeight = mViewport.deviceWidth;
3667 break;
3668 case DISPLAY_ORIENTATION_0:
3669 default:
3670 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3671 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3672 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3673 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3674 naturalPhysicalLeft = mViewport.physicalLeft;
3675 naturalPhysicalTop = mViewport.physicalTop;
3676 naturalDeviceWidth = mViewport.deviceWidth;
3677 naturalDeviceHeight = mViewport.deviceHeight;
3678 break;
3679 }
3680
Siarhei Vishniakoud6343922018-07-06 23:33:37 +01003681 if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
3682 ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
3683 naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
3684 naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
3685 }
3686
Michael Wright358bcc72018-08-21 04:01:07 +01003687 mPhysicalWidth = naturalPhysicalWidth;
3688 mPhysicalHeight = naturalPhysicalHeight;
3689 mPhysicalLeft = naturalPhysicalLeft;
3690 mPhysicalTop = naturalPhysicalTop;
3691
Michael Wrightd02c5b62014-02-10 15:10:22 -08003692 mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
3693 mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
3694 mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
3695 mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
3696
3697 mSurfaceOrientation = mParameters.orientationAware ?
3698 mViewport.orientation : DISPLAY_ORIENTATION_0;
3699 } else {
Michael Wright358bcc72018-08-21 04:01:07 +01003700 mPhysicalWidth = rawWidth;
3701 mPhysicalHeight = rawHeight;
3702 mPhysicalLeft = 0;
3703 mPhysicalTop = 0;
3704
Michael Wrightd02c5b62014-02-10 15:10:22 -08003705 mSurfaceWidth = rawWidth;
3706 mSurfaceHeight = rawHeight;
3707 mSurfaceLeft = 0;
3708 mSurfaceTop = 0;
3709 mSurfaceOrientation = DISPLAY_ORIENTATION_0;
3710 }
3711 }
3712
3713 // If moving between pointer modes, need to reset some state.
3714 bool deviceModeChanged = mDeviceMode != oldDeviceMode;
3715 if (deviceModeChanged) {
3716 mOrientedRanges.clear();
3717 }
3718
Arthur Hungc7ad2d02018-12-18 17:41:29 +08003719 // Create or update pointer controller if needed.
Michael Wrightd02c5b62014-02-10 15:10:22 -08003720 if (mDeviceMode == DEVICE_MODE_POINTER ||
3721 (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
Arthur Hungc7ad2d02018-12-18 17:41:29 +08003722 if (mPointerController == nullptr || viewportChanged) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003723 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
3724 }
3725 } else {
3726 mPointerController.clear();
3727 }
3728
3729 if (viewportChanged || deviceModeChanged) {
3730 ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
3731 "display id %d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003732 getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
Michael Wrightd02c5b62014-02-10 15:10:22 -08003733 mSurfaceOrientation, mDeviceMode, mViewport.displayId);
3734
3735 // Configure X and Y factors.
3736 mXScale = float(mSurfaceWidth) / rawWidth;
3737 mYScale = float(mSurfaceHeight) / rawHeight;
3738 mXTranslate = -mSurfaceLeft;
3739 mYTranslate = -mSurfaceTop;
3740 mXPrecision = 1.0f / mXScale;
3741 mYPrecision = 1.0f / mYScale;
3742
3743 mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
3744 mOrientedRanges.x.source = mSource;
3745 mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
3746 mOrientedRanges.y.source = mSource;
3747
3748 configureVirtualKeys();
3749
3750 // Scale factor for terms that are not oriented in a particular axis.
3751 // If the pixels are square then xScale == yScale otherwise we fake it
3752 // by choosing an average.
3753 mGeometricScale = avg(mXScale, mYScale);
3754
3755 // Size of diagonal axis.
3756 float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
3757
3758 // Size factors.
3759 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
3760 if (mRawPointerAxes.touchMajor.valid
3761 && mRawPointerAxes.touchMajor.maxValue != 0) {
3762 mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
3763 } else if (mRawPointerAxes.toolMajor.valid
3764 && mRawPointerAxes.toolMajor.maxValue != 0) {
3765 mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
3766 } else {
3767 mSizeScale = 0.0f;
3768 }
3769
3770 mOrientedRanges.haveTouchSize = true;
3771 mOrientedRanges.haveToolSize = true;
3772 mOrientedRanges.haveSize = true;
3773
3774 mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
3775 mOrientedRanges.touchMajor.source = mSource;
3776 mOrientedRanges.touchMajor.min = 0;
3777 mOrientedRanges.touchMajor.max = diagonalSize;
3778 mOrientedRanges.touchMajor.flat = 0;
3779 mOrientedRanges.touchMajor.fuzz = 0;
3780 mOrientedRanges.touchMajor.resolution = 0;
3781
3782 mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
3783 mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
3784
3785 mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
3786 mOrientedRanges.toolMajor.source = mSource;
3787 mOrientedRanges.toolMajor.min = 0;
3788 mOrientedRanges.toolMajor.max = diagonalSize;
3789 mOrientedRanges.toolMajor.flat = 0;
3790 mOrientedRanges.toolMajor.fuzz = 0;
3791 mOrientedRanges.toolMajor.resolution = 0;
3792
3793 mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
3794 mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
3795
3796 mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
3797 mOrientedRanges.size.source = mSource;
3798 mOrientedRanges.size.min = 0;
3799 mOrientedRanges.size.max = 1.0;
3800 mOrientedRanges.size.flat = 0;
3801 mOrientedRanges.size.fuzz = 0;
3802 mOrientedRanges.size.resolution = 0;
3803 } else {
3804 mSizeScale = 0.0f;
3805 }
3806
3807 // Pressure factors.
3808 mPressureScale = 0;
Michael Wrightaa449c92017-12-13 21:21:43 +00003809 float pressureMax = 1.0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003810 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
3811 || mCalibration.pressureCalibration
3812 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
3813 if (mCalibration.havePressureScale) {
3814 mPressureScale = mCalibration.pressureScale;
Michael Wrightaa449c92017-12-13 21:21:43 +00003815 pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003816 } else if (mRawPointerAxes.pressure.valid
3817 && mRawPointerAxes.pressure.maxValue != 0) {
3818 mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
3819 }
3820 }
3821
3822 mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
3823 mOrientedRanges.pressure.source = mSource;
3824 mOrientedRanges.pressure.min = 0;
Michael Wrightaa449c92017-12-13 21:21:43 +00003825 mOrientedRanges.pressure.max = pressureMax;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003826 mOrientedRanges.pressure.flat = 0;
3827 mOrientedRanges.pressure.fuzz = 0;
3828 mOrientedRanges.pressure.resolution = 0;
3829
3830 // Tilt
3831 mTiltXCenter = 0;
3832 mTiltXScale = 0;
3833 mTiltYCenter = 0;
3834 mTiltYScale = 0;
3835 mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
3836 if (mHaveTilt) {
3837 mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
3838 mRawPointerAxes.tiltX.maxValue);
3839 mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
3840 mRawPointerAxes.tiltY.maxValue);
3841 mTiltXScale = M_PI / 180;
3842 mTiltYScale = M_PI / 180;
3843
3844 mOrientedRanges.haveTilt = true;
3845
3846 mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
3847 mOrientedRanges.tilt.source = mSource;
3848 mOrientedRanges.tilt.min = 0;
3849 mOrientedRanges.tilt.max = M_PI_2;
3850 mOrientedRanges.tilt.flat = 0;
3851 mOrientedRanges.tilt.fuzz = 0;
3852 mOrientedRanges.tilt.resolution = 0;
3853 }
3854
3855 // Orientation
3856 mOrientationScale = 0;
3857 if (mHaveTilt) {
3858 mOrientedRanges.haveOrientation = true;
3859
3860 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3861 mOrientedRanges.orientation.source = mSource;
3862 mOrientedRanges.orientation.min = -M_PI;
3863 mOrientedRanges.orientation.max = M_PI;
3864 mOrientedRanges.orientation.flat = 0;
3865 mOrientedRanges.orientation.fuzz = 0;
3866 mOrientedRanges.orientation.resolution = 0;
3867 } else if (mCalibration.orientationCalibration !=
3868 Calibration::ORIENTATION_CALIBRATION_NONE) {
3869 if (mCalibration.orientationCalibration
3870 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
3871 if (mRawPointerAxes.orientation.valid) {
3872 if (mRawPointerAxes.orientation.maxValue > 0) {
3873 mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
3874 } else if (mRawPointerAxes.orientation.minValue < 0) {
3875 mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
3876 } else {
3877 mOrientationScale = 0;
3878 }
3879 }
3880 }
3881
3882 mOrientedRanges.haveOrientation = true;
3883
3884 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3885 mOrientedRanges.orientation.source = mSource;
3886 mOrientedRanges.orientation.min = -M_PI_2;
3887 mOrientedRanges.orientation.max = M_PI_2;
3888 mOrientedRanges.orientation.flat = 0;
3889 mOrientedRanges.orientation.fuzz = 0;
3890 mOrientedRanges.orientation.resolution = 0;
3891 }
3892
3893 // Distance
3894 mDistanceScale = 0;
3895 if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
3896 if (mCalibration.distanceCalibration
3897 == Calibration::DISTANCE_CALIBRATION_SCALED) {
3898 if (mCalibration.haveDistanceScale) {
3899 mDistanceScale = mCalibration.distanceScale;
3900 } else {
3901 mDistanceScale = 1.0f;
3902 }
3903 }
3904
3905 mOrientedRanges.haveDistance = true;
3906
3907 mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
3908 mOrientedRanges.distance.source = mSource;
3909 mOrientedRanges.distance.min =
3910 mRawPointerAxes.distance.minValue * mDistanceScale;
3911 mOrientedRanges.distance.max =
3912 mRawPointerAxes.distance.maxValue * mDistanceScale;
3913 mOrientedRanges.distance.flat = 0;
3914 mOrientedRanges.distance.fuzz =
3915 mRawPointerAxes.distance.fuzz * mDistanceScale;
3916 mOrientedRanges.distance.resolution = 0;
3917 }
3918
3919 // Compute oriented precision, scales and ranges.
3920 // Note that the maximum value reported is an inclusive maximum value so it is one
3921 // unit less than the total width or height of surface.
3922 switch (mSurfaceOrientation) {
3923 case DISPLAY_ORIENTATION_90:
3924 case DISPLAY_ORIENTATION_270:
3925 mOrientedXPrecision = mYPrecision;
3926 mOrientedYPrecision = mXPrecision;
3927
3928 mOrientedRanges.x.min = mYTranslate;
3929 mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
3930 mOrientedRanges.x.flat = 0;
3931 mOrientedRanges.x.fuzz = 0;
3932 mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
3933
3934 mOrientedRanges.y.min = mXTranslate;
3935 mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
3936 mOrientedRanges.y.flat = 0;
3937 mOrientedRanges.y.fuzz = 0;
3938 mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
3939 break;
3940
3941 default:
3942 mOrientedXPrecision = mXPrecision;
3943 mOrientedYPrecision = mYPrecision;
3944
3945 mOrientedRanges.x.min = mXTranslate;
3946 mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
3947 mOrientedRanges.x.flat = 0;
3948 mOrientedRanges.x.fuzz = 0;
3949 mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
3950
3951 mOrientedRanges.y.min = mYTranslate;
3952 mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
3953 mOrientedRanges.y.flat = 0;
3954 mOrientedRanges.y.fuzz = 0;
3955 mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
3956 break;
3957 }
3958
Jason Gerecke71b16e82014-03-10 09:47:59 -07003959 // Location
3960 updateAffineTransformation();
3961
Michael Wrightd02c5b62014-02-10 15:10:22 -08003962 if (mDeviceMode == DEVICE_MODE_POINTER) {
3963 // Compute pointer gesture detection parameters.
3964 float rawDiagonal = hypotf(rawWidth, rawHeight);
3965 float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
3966
3967 // Scale movements such that one whole swipe of the touch pad covers a
3968 // given area relative to the diagonal size of the display when no acceleration
3969 // is applied.
3970 // Assume that the touch pad has a square aspect ratio such that movements in
3971 // X and Y of the same number of raw units cover the same physical distance.
3972 mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
3973 * displayDiagonal / rawDiagonal;
3974 mPointerYMovementScale = mPointerXMovementScale;
3975
3976 // Scale zooms to cover a smaller range of the display than movements do.
3977 // This value determines the area around the pointer that is affected by freeform
3978 // pointer gestures.
3979 mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
3980 * displayDiagonal / rawDiagonal;
3981 mPointerYZoomScale = mPointerXZoomScale;
3982
3983 // Max width between pointers to detect a swipe gesture is more than some fraction
3984 // of the diagonal axis of the touch pad. Touches that are wider than this are
3985 // translated into freeform gestures.
3986 mPointerGestureMaxSwipeWidth =
3987 mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
3988
3989 // Abort current pointer usages because the state has changed.
3990 abortPointerUsage(when, 0 /*policyFlags*/);
3991 }
3992
3993 // Inform the dispatcher about the changes.
3994 *outResetNeeded = true;
3995 bumpGeneration();
3996 }
3997}
3998
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003999void TouchInputMapper::dumpSurface(std::string& dump) {
Siarhei Vishniakoud6343922018-07-06 23:33:37 +01004000 dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004001 dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
4002 dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
4003 dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
4004 dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
Michael Wright358bcc72018-08-21 04:01:07 +01004005 dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
4006 dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
4007 dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
4008 dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004009 dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004010}
4011
4012void TouchInputMapper::configureVirtualKeys() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004013 std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004014 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
4015
4016 mVirtualKeys.clear();
4017
4018 if (virtualKeyDefinitions.size() == 0) {
4019 return;
4020 }
4021
Michael Wrightd02c5b62014-02-10 15:10:22 -08004022 int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
4023 int32_t touchScreenTop = mRawPointerAxes.y.minValue;
Siarhei Vishniakou26e34d92018-11-12 13:51:26 -08004024 int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
4025 int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004026
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004027 for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
4028 VirtualKey virtualKey;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004029
4030 virtualKey.scanCode = virtualKeyDefinition.scanCode;
4031 int32_t keyCode;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07004032 int32_t dummyKeyMetaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004033 uint32_t flags;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07004034 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0,
4035 &keyCode, &dummyKeyMetaState, &flags)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004036 ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
4037 virtualKey.scanCode);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004038 continue; // drop the key
Michael Wrightd02c5b62014-02-10 15:10:22 -08004039 }
4040
4041 virtualKey.keyCode = keyCode;
4042 virtualKey.flags = flags;
4043
4044 // convert the key definition's display coordinates into touch coordinates for a hit box
4045 int32_t halfWidth = virtualKeyDefinition.width / 2;
4046 int32_t halfHeight = virtualKeyDefinition.height / 2;
4047
4048 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
4049 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
4050 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
4051 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
4052 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
4053 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
4054 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
4055 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004056 mVirtualKeys.push_back(virtualKey);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004057 }
4058}
4059
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004060void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004061 if (!mVirtualKeys.empty()) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004062 dump += INDENT3 "Virtual Keys:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004063
4064 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004065 const VirtualKey& virtualKey = mVirtualKeys[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004066 dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08004067 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
4068 i, virtualKey.scanCode, virtualKey.keyCode,
4069 virtualKey.hitLeft, virtualKey.hitRight,
4070 virtualKey.hitTop, virtualKey.hitBottom);
4071 }
4072 }
4073}
4074
4075void TouchInputMapper::parseCalibration() {
4076 const PropertyMap& in = getDevice()->getConfiguration();
4077 Calibration& out = mCalibration;
4078
4079 // Size
4080 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
4081 String8 sizeCalibrationString;
4082 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
4083 if (sizeCalibrationString == "none") {
4084 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
4085 } else if (sizeCalibrationString == "geometric") {
4086 out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
4087 } else if (sizeCalibrationString == "diameter") {
4088 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
4089 } else if (sizeCalibrationString == "box") {
4090 out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
4091 } else if (sizeCalibrationString == "area") {
4092 out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
4093 } else if (sizeCalibrationString != "default") {
4094 ALOGW("Invalid value for touch.size.calibration: '%s'",
4095 sizeCalibrationString.string());
4096 }
4097 }
4098
4099 out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
4100 out.sizeScale);
4101 out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
4102 out.sizeBias);
4103 out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
4104 out.sizeIsSummed);
4105
4106 // Pressure
4107 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
4108 String8 pressureCalibrationString;
4109 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
4110 if (pressureCalibrationString == "none") {
4111 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
4112 } else if (pressureCalibrationString == "physical") {
4113 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
4114 } else if (pressureCalibrationString == "amplitude") {
4115 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
4116 } else if (pressureCalibrationString != "default") {
4117 ALOGW("Invalid value for touch.pressure.calibration: '%s'",
4118 pressureCalibrationString.string());
4119 }
4120 }
4121
4122 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
4123 out.pressureScale);
4124
4125 // Orientation
4126 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
4127 String8 orientationCalibrationString;
4128 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
4129 if (orientationCalibrationString == "none") {
4130 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
4131 } else if (orientationCalibrationString == "interpolated") {
4132 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
4133 } else if (orientationCalibrationString == "vector") {
4134 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
4135 } else if (orientationCalibrationString != "default") {
4136 ALOGW("Invalid value for touch.orientation.calibration: '%s'",
4137 orientationCalibrationString.string());
4138 }
4139 }
4140
4141 // Distance
4142 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
4143 String8 distanceCalibrationString;
4144 if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
4145 if (distanceCalibrationString == "none") {
4146 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
4147 } else if (distanceCalibrationString == "scaled") {
4148 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
4149 } else if (distanceCalibrationString != "default") {
4150 ALOGW("Invalid value for touch.distance.calibration: '%s'",
4151 distanceCalibrationString.string());
4152 }
4153 }
4154
4155 out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
4156 out.distanceScale);
4157
4158 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
4159 String8 coverageCalibrationString;
4160 if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
4161 if (coverageCalibrationString == "none") {
4162 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
4163 } else if (coverageCalibrationString == "box") {
4164 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
4165 } else if (coverageCalibrationString != "default") {
4166 ALOGW("Invalid value for touch.coverage.calibration: '%s'",
4167 coverageCalibrationString.string());
4168 }
4169 }
4170}
4171
4172void TouchInputMapper::resolveCalibration() {
4173 // Size
4174 if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
4175 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
4176 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
4177 }
4178 } else {
4179 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
4180 }
4181
4182 // Pressure
4183 if (mRawPointerAxes.pressure.valid) {
4184 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
4185 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
4186 }
4187 } else {
4188 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
4189 }
4190
4191 // Orientation
4192 if (mRawPointerAxes.orientation.valid) {
4193 if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
4194 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
4195 }
4196 } else {
4197 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
4198 }
4199
4200 // Distance
4201 if (mRawPointerAxes.distance.valid) {
4202 if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
4203 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
4204 }
4205 } else {
4206 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
4207 }
4208
4209 // Coverage
4210 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
4211 mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
4212 }
4213}
4214
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004215void TouchInputMapper::dumpCalibration(std::string& dump) {
4216 dump += INDENT3 "Calibration:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004217
4218 // Size
4219 switch (mCalibration.sizeCalibration) {
4220 case Calibration::SIZE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004221 dump += INDENT4 "touch.size.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004222 break;
4223 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004224 dump += INDENT4 "touch.size.calibration: geometric\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004225 break;
4226 case Calibration::SIZE_CALIBRATION_DIAMETER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004227 dump += INDENT4 "touch.size.calibration: diameter\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004228 break;
4229 case Calibration::SIZE_CALIBRATION_BOX:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004230 dump += INDENT4 "touch.size.calibration: box\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004231 break;
4232 case Calibration::SIZE_CALIBRATION_AREA:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004233 dump += INDENT4 "touch.size.calibration: area\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004234 break;
4235 default:
4236 ALOG_ASSERT(false);
4237 }
4238
4239 if (mCalibration.haveSizeScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004240 dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004241 mCalibration.sizeScale);
4242 }
4243
4244 if (mCalibration.haveSizeBias) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004245 dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004246 mCalibration.sizeBias);
4247 }
4248
4249 if (mCalibration.haveSizeIsSummed) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004250 dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004251 toString(mCalibration.sizeIsSummed));
4252 }
4253
4254 // Pressure
4255 switch (mCalibration.pressureCalibration) {
4256 case Calibration::PRESSURE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004257 dump += INDENT4 "touch.pressure.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004258 break;
4259 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004260 dump += INDENT4 "touch.pressure.calibration: physical\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004261 break;
4262 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004263 dump += INDENT4 "touch.pressure.calibration: amplitude\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004264 break;
4265 default:
4266 ALOG_ASSERT(false);
4267 }
4268
4269 if (mCalibration.havePressureScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004270 dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004271 mCalibration.pressureScale);
4272 }
4273
4274 // Orientation
4275 switch (mCalibration.orientationCalibration) {
4276 case Calibration::ORIENTATION_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004277 dump += INDENT4 "touch.orientation.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004278 break;
4279 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004280 dump += INDENT4 "touch.orientation.calibration: interpolated\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004281 break;
4282 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004283 dump += INDENT4 "touch.orientation.calibration: vector\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004284 break;
4285 default:
4286 ALOG_ASSERT(false);
4287 }
4288
4289 // Distance
4290 switch (mCalibration.distanceCalibration) {
4291 case Calibration::DISTANCE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004292 dump += INDENT4 "touch.distance.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004293 break;
4294 case Calibration::DISTANCE_CALIBRATION_SCALED:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004295 dump += INDENT4 "touch.distance.calibration: scaled\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004296 break;
4297 default:
4298 ALOG_ASSERT(false);
4299 }
4300
4301 if (mCalibration.haveDistanceScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004302 dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004303 mCalibration.distanceScale);
4304 }
4305
4306 switch (mCalibration.coverageCalibration) {
4307 case Calibration::COVERAGE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004308 dump += INDENT4 "touch.coverage.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004309 break;
4310 case Calibration::COVERAGE_CALIBRATION_BOX:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004311 dump += INDENT4 "touch.coverage.calibration: box\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004312 break;
4313 default:
4314 ALOG_ASSERT(false);
4315 }
4316}
4317
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004318void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
4319 dump += INDENT3 "Affine Transformation:\n";
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004320
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004321 dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
4322 dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
4323 dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
4324 dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
4325 dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
4326 dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004327}
4328
Jason Gerecke12d6baa2014-01-27 18:34:20 -08004329void TouchInputMapper::updateAffineTransformation() {
Jason Gerecke71b16e82014-03-10 09:47:59 -07004330 mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
4331 mSurfaceOrientation);
Jason Gerecke12d6baa2014-01-27 18:34:20 -08004332}
4333
Michael Wrightd02c5b62014-02-10 15:10:22 -08004334void TouchInputMapper::reset(nsecs_t when) {
4335 mCursorButtonAccumulator.reset(getDevice());
4336 mCursorScrollAccumulator.reset(getDevice());
4337 mTouchButtonAccumulator.reset(getDevice());
4338
4339 mPointerVelocityControl.reset();
4340 mWheelXVelocityControl.reset();
4341 mWheelYVelocityControl.reset();
4342
Michael Wright842500e2015-03-13 17:32:02 -07004343 mRawStatesPending.clear();
4344 mCurrentRawState.clear();
4345 mCurrentCookedState.clear();
4346 mLastRawState.clear();
4347 mLastCookedState.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004348 mPointerUsage = POINTER_USAGE_NONE;
4349 mSentHoverEnter = false;
Michael Wright842500e2015-03-13 17:32:02 -07004350 mHavePointerIds = false;
Michael Wright8e812822015-06-22 16:18:21 +01004351 mCurrentMotionAborted = false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004352 mDownTime = 0;
4353
4354 mCurrentVirtualKey.down = false;
4355
4356 mPointerGesture.reset();
4357 mPointerSimple.reset();
Michael Wright842500e2015-03-13 17:32:02 -07004358 resetExternalStylus();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004359
Yi Kong9b14ac62018-07-17 13:48:38 -07004360 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004361 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4362 mPointerController->clearSpots();
4363 }
4364
4365 InputMapper::reset(when);
4366}
4367
Michael Wright842500e2015-03-13 17:32:02 -07004368void TouchInputMapper::resetExternalStylus() {
4369 mExternalStylusState.clear();
4370 mExternalStylusId = -1;
Michael Wright43fd19f2015-04-21 19:02:58 +01004371 mExternalStylusFusionTimeout = LLONG_MAX;
Michael Wright842500e2015-03-13 17:32:02 -07004372 mExternalStylusDataPending = false;
4373}
4374
Michael Wright43fd19f2015-04-21 19:02:58 +01004375void TouchInputMapper::clearStylusDataPendingFlags() {
4376 mExternalStylusDataPending = false;
4377 mExternalStylusFusionTimeout = LLONG_MAX;
4378}
4379
Michael Wrightd02c5b62014-02-10 15:10:22 -08004380void TouchInputMapper::process(const RawEvent* rawEvent) {
4381 mCursorButtonAccumulator.process(rawEvent);
4382 mCursorScrollAccumulator.process(rawEvent);
4383 mTouchButtonAccumulator.process(rawEvent);
4384
4385 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
4386 sync(rawEvent->when);
4387 }
4388}
4389
4390void TouchInputMapper::sync(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004391 const RawState* last = mRawStatesPending.empty() ?
4392 &mCurrentRawState : &mRawStatesPending.back();
Michael Wright842500e2015-03-13 17:32:02 -07004393
4394 // Push a new state.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004395 mRawStatesPending.emplace_back();
4396
4397 RawState* next = &mRawStatesPending.back();
Michael Wright842500e2015-03-13 17:32:02 -07004398 next->clear();
4399 next->when = when;
4400
Michael Wrightd02c5b62014-02-10 15:10:22 -08004401 // Sync button state.
Michael Wright842500e2015-03-13 17:32:02 -07004402 next->buttonState = mTouchButtonAccumulator.getButtonState()
Michael Wrightd02c5b62014-02-10 15:10:22 -08004403 | mCursorButtonAccumulator.getButtonState();
4404
Michael Wright842500e2015-03-13 17:32:02 -07004405 // Sync scroll
4406 next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
4407 next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004408 mCursorScrollAccumulator.finishSync();
4409
Michael Wright842500e2015-03-13 17:32:02 -07004410 // Sync touch
4411 syncTouch(when, next);
4412
4413 // Assign pointer ids.
4414 if (!mHavePointerIds) {
4415 assignPointerIds(last, next);
4416 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08004417
4418#if DEBUG_RAW_EVENTS
Michael Wright842500e2015-03-13 17:32:02 -07004419 ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
4420 "hovering ids 0x%08x -> 0x%08x",
4421 last->rawPointerData.pointerCount,
4422 next->rawPointerData.pointerCount,
4423 last->rawPointerData.touchingIdBits.value,
4424 next->rawPointerData.touchingIdBits.value,
4425 last->rawPointerData.hoveringIdBits.value,
4426 next->rawPointerData.hoveringIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004427#endif
4428
Michael Wright842500e2015-03-13 17:32:02 -07004429 processRawTouches(false /*timeout*/);
4430}
Michael Wrightd02c5b62014-02-10 15:10:22 -08004431
Michael Wright842500e2015-03-13 17:32:02 -07004432void TouchInputMapper::processRawTouches(bool timeout) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004433 if (mDeviceMode == DEVICE_MODE_DISABLED) {
4434 // Drop all input if the device is disabled.
Michael Wright842500e2015-03-13 17:32:02 -07004435 mCurrentRawState.clear();
4436 mRawStatesPending.clear();
4437 return;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004438 }
4439
Michael Wright842500e2015-03-13 17:32:02 -07004440 // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
4441 // valid and must go through the full cook and dispatch cycle. This ensures that anything
4442 // touching the current state will only observe the events that have been dispatched to the
4443 // rest of the pipeline.
4444 const size_t N = mRawStatesPending.size();
4445 size_t count;
4446 for(count = 0; count < N; count++) {
4447 const RawState& next = mRawStatesPending[count];
4448
4449 // A failure to assign the stylus id means that we're waiting on stylus data
4450 // and so should defer the rest of the pipeline.
4451 if (assignExternalStylusId(next, timeout)) {
4452 break;
4453 }
4454
4455 // All ready to go.
Michael Wright43fd19f2015-04-21 19:02:58 +01004456 clearStylusDataPendingFlags();
Michael Wright842500e2015-03-13 17:32:02 -07004457 mCurrentRawState.copyFrom(next);
Michael Wright43fd19f2015-04-21 19:02:58 +01004458 if (mCurrentRawState.when < mLastRawState.when) {
4459 mCurrentRawState.when = mLastRawState.when;
4460 }
Michael Wright842500e2015-03-13 17:32:02 -07004461 cookAndDispatch(mCurrentRawState.when);
4462 }
4463 if (count != 0) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004464 mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
Michael Wright842500e2015-03-13 17:32:02 -07004465 }
4466
Michael Wright842500e2015-03-13 17:32:02 -07004467 if (mExternalStylusDataPending) {
Michael Wright43fd19f2015-04-21 19:02:58 +01004468 if (timeout) {
4469 nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
4470 clearStylusDataPendingFlags();
4471 mCurrentRawState.copyFrom(mLastRawState);
4472#if DEBUG_STYLUS_FUSION
4473 ALOGD("Timeout expired, synthesizing event with new stylus data");
4474#endif
4475 cookAndDispatch(when);
4476 } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
4477 mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
4478 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
4479 }
Michael Wright842500e2015-03-13 17:32:02 -07004480 }
4481}
4482
4483void TouchInputMapper::cookAndDispatch(nsecs_t when) {
4484 // Always start with a clean state.
4485 mCurrentCookedState.clear();
4486
4487 // Apply stylus buttons to current raw state.
4488 applyExternalStylusButtonState(when);
4489
4490 // Handle policy on initial down or hover events.
4491 bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4492 && mCurrentRawState.rawPointerData.pointerCount != 0;
4493
4494 uint32_t policyFlags = 0;
4495 bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
4496 if (initialDown || buttonsPressed) {
4497 // If this is a touch screen, hide the pointer on an initial down.
4498 if (mDeviceMode == DEVICE_MODE_DIRECT) {
4499 getContext()->fadePointer();
4500 }
4501
4502 if (mParameters.wake) {
4503 policyFlags |= POLICY_FLAG_WAKE;
4504 }
4505 }
4506
4507 // Consume raw off-screen touches before cooking pointer data.
4508 // If touches are consumed, subsequent code will not receive any pointer data.
4509 if (consumeRawTouches(when, policyFlags)) {
4510 mCurrentRawState.rawPointerData.clear();
4511 }
4512
4513 // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
4514 // with cooked pointer data that has the same ids and indices as the raw data.
4515 // The following code can use either the raw or cooked data, as needed.
4516 cookPointerData();
4517
4518 // Apply stylus pressure to current cooked state.
4519 applyExternalStylusTouchState(when);
4520
4521 // Synthesize key down from raw buttons if needed.
4522 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004523 mViewport.displayId, policyFlags,
4524 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
Michael Wright842500e2015-03-13 17:32:02 -07004525
4526 // Dispatch the touches either directly or by translation through a pointer on screen.
4527 if (mDeviceMode == DEVICE_MODE_POINTER) {
4528 for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
4529 !idBits.isEmpty(); ) {
4530 uint32_t id = idBits.clearFirstMarkedBit();
4531 const RawPointerData::Pointer& pointer =
4532 mCurrentRawState.rawPointerData.pointerForId(id);
4533 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
4534 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4535 mCurrentCookedState.stylusIdBits.markBit(id);
4536 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
4537 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4538 mCurrentCookedState.fingerIdBits.markBit(id);
4539 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
4540 mCurrentCookedState.mouseIdBits.markBit(id);
4541 }
4542 }
4543 for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
4544 !idBits.isEmpty(); ) {
4545 uint32_t id = idBits.clearFirstMarkedBit();
4546 const RawPointerData::Pointer& pointer =
4547 mCurrentRawState.rawPointerData.pointerForId(id);
4548 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
4549 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4550 mCurrentCookedState.stylusIdBits.markBit(id);
4551 }
4552 }
4553
4554 // Stylus takes precedence over all tools, then mouse, then finger.
4555 PointerUsage pointerUsage = mPointerUsage;
4556 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
4557 mCurrentCookedState.mouseIdBits.clear();
4558 mCurrentCookedState.fingerIdBits.clear();
4559 pointerUsage = POINTER_USAGE_STYLUS;
4560 } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
4561 mCurrentCookedState.fingerIdBits.clear();
4562 pointerUsage = POINTER_USAGE_MOUSE;
4563 } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
4564 isPointerDown(mCurrentRawState.buttonState)) {
4565 pointerUsage = POINTER_USAGE_GESTURES;
4566 }
4567
4568 dispatchPointerUsage(when, policyFlags, pointerUsage);
4569 } else {
4570 if (mDeviceMode == DEVICE_MODE_DIRECT
Yi Kong9b14ac62018-07-17 13:48:38 -07004571 && mConfig.showTouches && mPointerController != nullptr) {
Michael Wright842500e2015-03-13 17:32:02 -07004572 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
4573 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4574
4575 mPointerController->setButtonState(mCurrentRawState.buttonState);
4576 mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
4577 mCurrentCookedState.cookedPointerData.idToIndex,
Arthur Hung7c645402019-01-25 17:45:42 +08004578 mCurrentCookedState.cookedPointerData.touchingIdBits,
4579 mViewport.displayId);
Michael Wright842500e2015-03-13 17:32:02 -07004580 }
4581
Michael Wright8e812822015-06-22 16:18:21 +01004582 if (!mCurrentMotionAborted) {
4583 dispatchButtonRelease(when, policyFlags);
4584 dispatchHoverExit(when, policyFlags);
4585 dispatchTouches(when, policyFlags);
4586 dispatchHoverEnterAndMove(when, policyFlags);
4587 dispatchButtonPress(when, policyFlags);
4588 }
4589
4590 if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
4591 mCurrentMotionAborted = false;
4592 }
Michael Wright842500e2015-03-13 17:32:02 -07004593 }
4594
4595 // Synthesize key up from raw buttons if needed.
4596 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004597 mViewport.displayId, policyFlags,
4598 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004599
4600 // Clear some transient state.
Michael Wright842500e2015-03-13 17:32:02 -07004601 mCurrentRawState.rawVScroll = 0;
4602 mCurrentRawState.rawHScroll = 0;
4603
4604 // Copy current touch to last touch in preparation for the next cycle.
4605 mLastRawState.copyFrom(mCurrentRawState);
4606 mLastCookedState.copyFrom(mCurrentCookedState);
4607}
4608
4609void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
Michael Wright7b159c92015-05-14 14:48:03 +01004610 if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
Michael Wright842500e2015-03-13 17:32:02 -07004611 mCurrentRawState.buttonState |= mExternalStylusState.buttons;
4612 }
4613}
4614
4615void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
Michael Wright53dca3a2015-04-23 17:39:53 +01004616 CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
4617 const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
Michael Wright842500e2015-03-13 17:32:02 -07004618
Michael Wright53dca3a2015-04-23 17:39:53 +01004619 if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
4620 float pressure = mExternalStylusState.pressure;
4621 if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
4622 const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
4623 pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
4624 }
4625 PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
4626 coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
4627
4628 PointerProperties& properties =
4629 currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
Michael Wright842500e2015-03-13 17:32:02 -07004630 if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4631 properties.toolType = mExternalStylusState.toolType;
4632 }
4633 }
4634}
4635
4636bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
4637 if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
4638 return false;
4639 }
4640
4641 const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4642 && state.rawPointerData.pointerCount != 0;
4643 if (initialDown) {
4644 if (mExternalStylusState.pressure != 0.0f) {
4645#if DEBUG_STYLUS_FUSION
4646 ALOGD("Have both stylus and touch data, beginning fusion");
4647#endif
4648 mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
4649 } else if (timeout) {
4650#if DEBUG_STYLUS_FUSION
4651 ALOGD("Timeout expired, assuming touch is not a stylus.");
4652#endif
4653 resetExternalStylus();
4654 } else {
Michael Wright43fd19f2015-04-21 19:02:58 +01004655 if (mExternalStylusFusionTimeout == LLONG_MAX) {
4656 mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
Michael Wright842500e2015-03-13 17:32:02 -07004657 }
4658#if DEBUG_STYLUS_FUSION
4659 ALOGD("No stylus data but stylus is connected, requesting timeout "
Michael Wright43fd19f2015-04-21 19:02:58 +01004660 "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004661#endif
Michael Wright43fd19f2015-04-21 19:02:58 +01004662 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004663 return true;
4664 }
4665 }
4666
4667 // Check if the stylus pointer has gone up.
4668 if (mExternalStylusId != -1 &&
4669 !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
4670#if DEBUG_STYLUS_FUSION
4671 ALOGD("Stylus pointer is going up");
4672#endif
4673 mExternalStylusId = -1;
4674 }
4675
4676 return false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004677}
4678
4679void TouchInputMapper::timeoutExpired(nsecs_t when) {
4680 if (mDeviceMode == DEVICE_MODE_POINTER) {
4681 if (mPointerUsage == POINTER_USAGE_GESTURES) {
4682 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
4683 }
Michael Wright842500e2015-03-13 17:32:02 -07004684 } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
Michael Wright43fd19f2015-04-21 19:02:58 +01004685 if (mExternalStylusFusionTimeout < when) {
Michael Wright842500e2015-03-13 17:32:02 -07004686 processRawTouches(true /*timeout*/);
Michael Wright43fd19f2015-04-21 19:02:58 +01004687 } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
4688 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004689 }
4690 }
4691}
4692
4693void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
Michael Wright4af18b92015-04-20 22:03:54 +01004694 mExternalStylusState.copyFrom(state);
Michael Wright43fd19f2015-04-21 19:02:58 +01004695 if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
Michael Wright842500e2015-03-13 17:32:02 -07004696 // We're either in the middle of a fused stream of data or we're waiting on data before
4697 // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
4698 // data.
Michael Wright842500e2015-03-13 17:32:02 -07004699 mExternalStylusDataPending = true;
Michael Wright842500e2015-03-13 17:32:02 -07004700 processRawTouches(false /*timeout*/);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004701 }
4702}
4703
4704bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
4705 // Check for release of a virtual key.
4706 if (mCurrentVirtualKey.down) {
Michael Wright842500e2015-03-13 17:32:02 -07004707 if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004708 // Pointer went up while virtual key was down.
4709 mCurrentVirtualKey.down = false;
4710 if (!mCurrentVirtualKey.ignored) {
4711#if DEBUG_VIRTUAL_KEYS
4712 ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
4713 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4714#endif
4715 dispatchVirtualKey(when, policyFlags,
4716 AKEY_EVENT_ACTION_UP,
4717 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4718 }
4719 return true;
4720 }
4721
Michael Wright842500e2015-03-13 17:32:02 -07004722 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
4723 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4724 const RawPointerData::Pointer& pointer =
4725 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004726 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4727 if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
4728 // Pointer is still within the space of the virtual key.
4729 return true;
4730 }
4731 }
4732
4733 // Pointer left virtual key area or another pointer also went down.
4734 // Send key cancellation but do not consume the touch yet.
4735 // This is useful when the user swipes through from the virtual key area
4736 // into the main display surface.
4737 mCurrentVirtualKey.down = false;
4738 if (!mCurrentVirtualKey.ignored) {
4739#if DEBUG_VIRTUAL_KEYS
4740 ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
4741 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4742#endif
4743 dispatchVirtualKey(when, policyFlags,
4744 AKEY_EVENT_ACTION_UP,
4745 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4746 | AKEY_EVENT_FLAG_CANCELED);
4747 }
4748 }
4749
Michael Wright842500e2015-03-13 17:32:02 -07004750 if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
4751 && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004752 // Pointer just went down. Check for virtual key press or off-screen touches.
Michael Wright842500e2015-03-13 17:32:02 -07004753 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4754 const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004755 if (!isPointInsideSurface(pointer.x, pointer.y)) {
4756 // If exactly one pointer went down, check for virtual key hit.
4757 // Otherwise we will drop the entire stroke.
Michael Wright842500e2015-03-13 17:32:02 -07004758 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004759 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4760 if (virtualKey) {
4761 mCurrentVirtualKey.down = true;
4762 mCurrentVirtualKey.downTime = when;
4763 mCurrentVirtualKey.keyCode = virtualKey->keyCode;
4764 mCurrentVirtualKey.scanCode = virtualKey->scanCode;
4765 mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
4766 when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
4767
4768 if (!mCurrentVirtualKey.ignored) {
4769#if DEBUG_VIRTUAL_KEYS
4770 ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
4771 mCurrentVirtualKey.keyCode,
4772 mCurrentVirtualKey.scanCode);
4773#endif
4774 dispatchVirtualKey(when, policyFlags,
4775 AKEY_EVENT_ACTION_DOWN,
4776 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4777 }
4778 }
4779 }
4780 return true;
4781 }
4782 }
4783
4784 // Disable all virtual key touches that happen within a short time interval of the
4785 // most recent touch within the screen area. The idea is to filter out stray
4786 // virtual key presses when interacting with the touch screen.
4787 //
4788 // Problems we're trying to solve:
4789 //
4790 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
4791 // virtual key area that is implemented by a separate touch panel and accidentally
4792 // triggers a virtual key.
4793 //
4794 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
4795 // area and accidentally triggers a virtual key. This often happens when virtual keys
4796 // are layed out below the screen near to where the on screen keyboard's space bar
4797 // is displayed.
Michael Wright842500e2015-03-13 17:32:02 -07004798 if (mConfig.virtualKeyQuietTime > 0 &&
4799 !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004800 mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
4801 }
4802 return false;
4803}
4804
4805void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
4806 int32_t keyEventAction, int32_t keyEventFlags) {
4807 int32_t keyCode = mCurrentVirtualKey.keyCode;
4808 int32_t scanCode = mCurrentVirtualKey.scanCode;
4809 nsecs_t downTime = mCurrentVirtualKey.downTime;
4810 int32_t metaState = mContext->getGlobalMetaState();
4811 policyFlags |= POLICY_FLAG_VIRTUAL;
4812
Prabir Pradhan42611e02018-11-27 14:04:02 -08004813 NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
4814 mViewport.displayId,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004815 policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004816 getListener()->notifyKey(&args);
4817}
4818
Michael Wright8e812822015-06-22 16:18:21 +01004819void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
4820 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4821 if (!currentIdBits.isEmpty()) {
4822 int32_t metaState = getContext()->getGlobalMetaState();
4823 int32_t buttonState = mCurrentCookedState.buttonState;
4824 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
4825 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4826 mCurrentCookedState.cookedPointerData.pointerProperties,
4827 mCurrentCookedState.cookedPointerData.pointerCoords,
4828 mCurrentCookedState.cookedPointerData.idToIndex,
4829 currentIdBits, -1,
4830 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4831 mCurrentMotionAborted = true;
4832 }
4833}
4834
Michael Wrightd02c5b62014-02-10 15:10:22 -08004835void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004836 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4837 BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004838 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01004839 int32_t buttonState = mCurrentCookedState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004840
4841 if (currentIdBits == lastIdBits) {
4842 if (!currentIdBits.isEmpty()) {
4843 // No pointer id changes so this is a move event.
4844 // The listener takes care of batching moves so we don't have to deal with that here.
4845 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004846 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004847 AMOTION_EVENT_EDGE_FLAG_NONE,
Michael Wright842500e2015-03-13 17:32:02 -07004848 mCurrentCookedState.cookedPointerData.pointerProperties,
4849 mCurrentCookedState.cookedPointerData.pointerCoords,
4850 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004851 currentIdBits, -1,
4852 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4853 }
4854 } else {
4855 // There may be pointers going up and pointers going down and pointers moving
4856 // all at the same time.
4857 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
4858 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
4859 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
4860 BitSet32 dispatchedIdBits(lastIdBits.value);
4861
4862 // Update last coordinates of pointers that have moved so that we observe the new
4863 // pointer positions at the same time as other pointers that have just gone up.
4864 bool moveNeeded = updateMovedPointers(
Michael Wright842500e2015-03-13 17:32:02 -07004865 mCurrentCookedState.cookedPointerData.pointerProperties,
4866 mCurrentCookedState.cookedPointerData.pointerCoords,
4867 mCurrentCookedState.cookedPointerData.idToIndex,
4868 mLastCookedState.cookedPointerData.pointerProperties,
4869 mLastCookedState.cookedPointerData.pointerCoords,
4870 mLastCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004871 moveIdBits);
Michael Wright7b159c92015-05-14 14:48:03 +01004872 if (buttonState != mLastCookedState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004873 moveNeeded = true;
4874 }
4875
4876 // Dispatch pointer up events.
4877 while (!upIdBits.isEmpty()) {
4878 uint32_t upId = upIdBits.clearFirstMarkedBit();
4879
4880 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004881 AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004882 mLastCookedState.cookedPointerData.pointerProperties,
4883 mLastCookedState.cookedPointerData.pointerCoords,
4884 mLastCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004885 dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004886 dispatchedIdBits.clearBit(upId);
4887 }
4888
4889 // Dispatch move events if any of the remaining pointers moved from their old locations.
4890 // Although applications receive new locations as part of individual pointer up
4891 // events, they do not generally handle them except when presented in a move event.
Michael Wright43fd19f2015-04-21 19:02:58 +01004892 if (moveNeeded && !moveIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004893 ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
4894 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004895 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004896 mCurrentCookedState.cookedPointerData.pointerProperties,
4897 mCurrentCookedState.cookedPointerData.pointerCoords,
4898 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004899 dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004900 }
4901
4902 // Dispatch pointer down events using the new pointer locations.
4903 while (!downIdBits.isEmpty()) {
4904 uint32_t downId = downIdBits.clearFirstMarkedBit();
4905 dispatchedIdBits.markBit(downId);
4906
4907 if (dispatchedIdBits.count() == 1) {
4908 // First pointer is going down. Set down time.
4909 mDownTime = when;
4910 }
4911
4912 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004913 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004914 mCurrentCookedState.cookedPointerData.pointerProperties,
4915 mCurrentCookedState.cookedPointerData.pointerCoords,
4916 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004917 dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004918 }
4919 }
4920}
4921
4922void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
4923 if (mSentHoverEnter &&
Michael Wright842500e2015-03-13 17:32:02 -07004924 (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
4925 || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004926 int32_t metaState = getContext()->getGlobalMetaState();
4927 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004928 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004929 mLastCookedState.cookedPointerData.pointerProperties,
4930 mLastCookedState.cookedPointerData.pointerCoords,
4931 mLastCookedState.cookedPointerData.idToIndex,
4932 mLastCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004933 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4934 mSentHoverEnter = false;
4935 }
4936}
4937
4938void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004939 if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
4940 && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004941 int32_t metaState = getContext()->getGlobalMetaState();
4942 if (!mSentHoverEnter) {
Michael Wright842500e2015-03-13 17:32:02 -07004943 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
Michael Wright7b159c92015-05-14 14:48:03 +01004944 0, 0, metaState, mCurrentRawState.buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004945 mCurrentCookedState.cookedPointerData.pointerProperties,
4946 mCurrentCookedState.cookedPointerData.pointerCoords,
4947 mCurrentCookedState.cookedPointerData.idToIndex,
4948 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004949 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4950 mSentHoverEnter = true;
4951 }
4952
4953 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004954 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
Michael Wright842500e2015-03-13 17:32:02 -07004955 mCurrentRawState.buttonState, 0,
4956 mCurrentCookedState.cookedPointerData.pointerProperties,
4957 mCurrentCookedState.cookedPointerData.pointerCoords,
4958 mCurrentCookedState.cookedPointerData.idToIndex,
4959 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004960 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4961 }
4962}
4963
Michael Wright7b159c92015-05-14 14:48:03 +01004964void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
4965 BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
4966 const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
4967 const int32_t metaState = getContext()->getGlobalMetaState();
4968 int32_t buttonState = mLastCookedState.buttonState;
4969 while (!releasedButtons.isEmpty()) {
4970 int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
4971 buttonState &= ~actionButton;
4972 dispatchMotion(when, policyFlags, mSource,
4973 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
4974 0, metaState, buttonState, 0,
4975 mCurrentCookedState.cookedPointerData.pointerProperties,
4976 mCurrentCookedState.cookedPointerData.pointerCoords,
4977 mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
4978 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4979 }
4980}
4981
4982void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
4983 BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
4984 const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
4985 const int32_t metaState = getContext()->getGlobalMetaState();
4986 int32_t buttonState = mLastCookedState.buttonState;
4987 while (!pressedButtons.isEmpty()) {
4988 int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
4989 buttonState |= actionButton;
4990 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
4991 0, metaState, buttonState, 0,
4992 mCurrentCookedState.cookedPointerData.pointerProperties,
4993 mCurrentCookedState.cookedPointerData.pointerCoords,
4994 mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
4995 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4996 }
4997}
4998
4999const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
5000 if (!cookedPointerData.touchingIdBits.isEmpty()) {
5001 return cookedPointerData.touchingIdBits;
5002 }
5003 return cookedPointerData.hoveringIdBits;
5004}
5005
Michael Wrightd02c5b62014-02-10 15:10:22 -08005006void TouchInputMapper::cookPointerData() {
Michael Wright842500e2015-03-13 17:32:02 -07005007 uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005008
Michael Wright842500e2015-03-13 17:32:02 -07005009 mCurrentCookedState.cookedPointerData.clear();
5010 mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
5011 mCurrentCookedState.cookedPointerData.hoveringIdBits =
5012 mCurrentRawState.rawPointerData.hoveringIdBits;
5013 mCurrentCookedState.cookedPointerData.touchingIdBits =
5014 mCurrentRawState.rawPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005015
Michael Wright7b159c92015-05-14 14:48:03 +01005016 if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
5017 mCurrentCookedState.buttonState = 0;
5018 } else {
5019 mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
5020 }
5021
Michael Wrightd02c5b62014-02-10 15:10:22 -08005022 // Walk through the the active pointers and map device coordinates onto
5023 // surface coordinates and adjust for display orientation.
5024 for (uint32_t i = 0; i < currentPointerCount; i++) {
Michael Wright842500e2015-03-13 17:32:02 -07005025 const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005026
5027 // Size
5028 float touchMajor, touchMinor, toolMajor, toolMinor, size;
5029 switch (mCalibration.sizeCalibration) {
5030 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
5031 case Calibration::SIZE_CALIBRATION_DIAMETER:
5032 case Calibration::SIZE_CALIBRATION_BOX:
5033 case Calibration::SIZE_CALIBRATION_AREA:
5034 if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
5035 touchMajor = in.touchMajor;
5036 touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
5037 toolMajor = in.toolMajor;
5038 toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
5039 size = mRawPointerAxes.touchMinor.valid
5040 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
5041 } else if (mRawPointerAxes.touchMajor.valid) {
5042 toolMajor = touchMajor = in.touchMajor;
5043 toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
5044 ? in.touchMinor : in.touchMajor;
5045 size = mRawPointerAxes.touchMinor.valid
5046 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
5047 } else if (mRawPointerAxes.toolMajor.valid) {
5048 touchMajor = toolMajor = in.toolMajor;
5049 touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
5050 ? in.toolMinor : in.toolMajor;
5051 size = mRawPointerAxes.toolMinor.valid
5052 ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
5053 } else {
5054 ALOG_ASSERT(false, "No touch or tool axes. "
5055 "Size calibration should have been resolved to NONE.");
5056 touchMajor = 0;
5057 touchMinor = 0;
5058 toolMajor = 0;
5059 toolMinor = 0;
5060 size = 0;
5061 }
5062
5063 if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
Michael Wright842500e2015-03-13 17:32:02 -07005064 uint32_t touchingCount =
5065 mCurrentRawState.rawPointerData.touchingIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005066 if (touchingCount > 1) {
5067 touchMajor /= touchingCount;
5068 touchMinor /= touchingCount;
5069 toolMajor /= touchingCount;
5070 toolMinor /= touchingCount;
5071 size /= touchingCount;
5072 }
5073 }
5074
5075 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
5076 touchMajor *= mGeometricScale;
5077 touchMinor *= mGeometricScale;
5078 toolMajor *= mGeometricScale;
5079 toolMinor *= mGeometricScale;
5080 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
5081 touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
5082 touchMinor = touchMajor;
5083 toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
5084 toolMinor = toolMajor;
5085 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
5086 touchMinor = touchMajor;
5087 toolMinor = toolMajor;
5088 }
5089
5090 mCalibration.applySizeScaleAndBias(&touchMajor);
5091 mCalibration.applySizeScaleAndBias(&touchMinor);
5092 mCalibration.applySizeScaleAndBias(&toolMajor);
5093 mCalibration.applySizeScaleAndBias(&toolMinor);
5094 size *= mSizeScale;
5095 break;
5096 default:
5097 touchMajor = 0;
5098 touchMinor = 0;
5099 toolMajor = 0;
5100 toolMinor = 0;
5101 size = 0;
5102 break;
5103 }
5104
5105 // Pressure
5106 float pressure;
5107 switch (mCalibration.pressureCalibration) {
5108 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
5109 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
5110 pressure = in.pressure * mPressureScale;
5111 break;
5112 default:
5113 pressure = in.isHovering ? 0 : 1;
5114 break;
5115 }
5116
5117 // Tilt and Orientation
5118 float tilt;
5119 float orientation;
5120 if (mHaveTilt) {
5121 float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
5122 float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
5123 orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5124 tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5125 } else {
5126 tilt = 0;
5127
5128 switch (mCalibration.orientationCalibration) {
5129 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
5130 orientation = in.orientation * mOrientationScale;
5131 break;
5132 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
5133 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
5134 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
5135 if (c1 != 0 || c2 != 0) {
5136 orientation = atan2f(c1, c2) * 0.5f;
5137 float confidence = hypotf(c1, c2);
5138 float scale = 1.0f + confidence / 16.0f;
5139 touchMajor *= scale;
5140 touchMinor /= scale;
5141 toolMajor *= scale;
5142 toolMinor /= scale;
5143 } else {
5144 orientation = 0;
5145 }
5146 break;
5147 }
5148 default:
5149 orientation = 0;
5150 }
5151 }
5152
5153 // Distance
5154 float distance;
5155 switch (mCalibration.distanceCalibration) {
5156 case Calibration::DISTANCE_CALIBRATION_SCALED:
5157 distance = in.distance * mDistanceScale;
5158 break;
5159 default:
5160 distance = 0;
5161 }
5162
5163 // Coverage
5164 int32_t rawLeft, rawTop, rawRight, rawBottom;
5165 switch (mCalibration.coverageCalibration) {
5166 case Calibration::COVERAGE_CALIBRATION_BOX:
5167 rawLeft = (in.toolMinor & 0xffff0000) >> 16;
5168 rawRight = in.toolMinor & 0x0000ffff;
5169 rawBottom = in.toolMajor & 0x0000ffff;
5170 rawTop = (in.toolMajor & 0xffff0000) >> 16;
5171 break;
5172 default:
5173 rawLeft = rawTop = rawRight = rawBottom = 0;
5174 break;
5175 }
5176
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005177 // Adjust X,Y coords for device calibration
5178 // TODO: Adjust coverage coords?
5179 float xTransformed = in.x, yTransformed = in.y;
5180 mAffineTransform.applyTo(xTransformed, yTransformed);
5181
5182 // Adjust X, Y, and coverage coords for surface orientation.
5183 float x, y;
5184 float left, top, right, bottom;
5185
Michael Wrightd02c5b62014-02-10 15:10:22 -08005186 switch (mSurfaceOrientation) {
5187 case DISPLAY_ORIENTATION_90:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005188 x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5189 y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005190 left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5191 right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5192 bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
5193 top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
5194 orientation -= M_PI_2;
baik.han18a81482015-04-14 19:49:28 +09005195 if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005196 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5197 }
5198 break;
5199 case DISPLAY_ORIENTATION_180:
Michael Wright358bcc72018-08-21 04:01:07 +01005200 x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005201 y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
Michael Wright358bcc72018-08-21 04:01:07 +01005202 left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
5203 right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005204 bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
5205 top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
5206 orientation -= M_PI;
baik.han18a81482015-04-14 19:49:28 +09005207 if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005208 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5209 }
5210 break;
5211 case DISPLAY_ORIENTATION_270:
Michael Wright358bcc72018-08-21 04:01:07 +01005212 x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005213 y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
Michael Wright358bcc72018-08-21 04:01:07 +01005214 left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
5215 right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005216 bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5217 top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5218 orientation += M_PI_2;
baik.han18a81482015-04-14 19:49:28 +09005219 if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005220 orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5221 }
5222 break;
5223 default:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005224 x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5225 y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005226 left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5227 right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5228 bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5229 top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5230 break;
5231 }
5232
5233 // Write output coords.
Michael Wright842500e2015-03-13 17:32:02 -07005234 PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005235 out.clear();
5236 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5237 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5238 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
5239 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
5240 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
5241 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
5242 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
5243 out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
5244 out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
5245 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
5246 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
5247 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
5248 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
5249 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
5250 } else {
5251 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
5252 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
5253 }
5254
5255 // Write output properties.
Michael Wright842500e2015-03-13 17:32:02 -07005256 PointerProperties& properties =
5257 mCurrentCookedState.cookedPointerData.pointerProperties[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005258 uint32_t id = in.id;
5259 properties.clear();
5260 properties.id = id;
5261 properties.toolType = in.toolType;
5262
5263 // Write id index.
Michael Wright842500e2015-03-13 17:32:02 -07005264 mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005265 }
5266}
5267
5268void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
5269 PointerUsage pointerUsage) {
5270 if (pointerUsage != mPointerUsage) {
5271 abortPointerUsage(when, policyFlags);
5272 mPointerUsage = pointerUsage;
5273 }
5274
5275 switch (mPointerUsage) {
5276 case POINTER_USAGE_GESTURES:
5277 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
5278 break;
5279 case POINTER_USAGE_STYLUS:
5280 dispatchPointerStylus(when, policyFlags);
5281 break;
5282 case POINTER_USAGE_MOUSE:
5283 dispatchPointerMouse(when, policyFlags);
5284 break;
5285 default:
5286 break;
5287 }
5288}
5289
5290void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
5291 switch (mPointerUsage) {
5292 case POINTER_USAGE_GESTURES:
5293 abortPointerGestures(when, policyFlags);
5294 break;
5295 case POINTER_USAGE_STYLUS:
5296 abortPointerStylus(when, policyFlags);
5297 break;
5298 case POINTER_USAGE_MOUSE:
5299 abortPointerMouse(when, policyFlags);
5300 break;
5301 default:
5302 break;
5303 }
5304
5305 mPointerUsage = POINTER_USAGE_NONE;
5306}
5307
5308void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
5309 bool isTimeout) {
5310 // Update current gesture coordinates.
5311 bool cancelPreviousGesture, finishPreviousGesture;
5312 bool sendEvents = preparePointerGestures(when,
5313 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
5314 if (!sendEvents) {
5315 return;
5316 }
5317 if (finishPreviousGesture) {
5318 cancelPreviousGesture = false;
5319 }
5320
5321 // Update the pointer presentation and spots.
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005322 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
5323 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005324 if (finishPreviousGesture || cancelPreviousGesture) {
5325 mPointerController->clearSpots();
5326 }
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005327
5328 if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
5329 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
5330 mPointerGesture.currentGestureIdToIndex,
Arthur Hung7c645402019-01-25 17:45:42 +08005331 mPointerGesture.currentGestureIdBits,
5332 mPointerController->getDisplayId());
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005333 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08005334 } else {
5335 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5336 }
5337
5338 // Show or hide the pointer if needed.
5339 switch (mPointerGesture.currentGestureMode) {
5340 case PointerGesture::NEUTRAL:
5341 case PointerGesture::QUIET:
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005342 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
5343 && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005344 // Remind the user of where the pointer is after finishing a gesture with spots.
5345 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
5346 }
5347 break;
5348 case PointerGesture::TAP:
5349 case PointerGesture::TAP_DRAG:
5350 case PointerGesture::BUTTON_CLICK_OR_DRAG:
5351 case PointerGesture::HOVER:
5352 case PointerGesture::PRESS:
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005353 case PointerGesture::SWIPE:
Michael Wrightd02c5b62014-02-10 15:10:22 -08005354 // Unfade the pointer when the current gesture manipulates the
5355 // area directly under the pointer.
5356 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5357 break;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005358 case PointerGesture::FREEFORM:
5359 // Fade the pointer when the current gesture manipulates a different
5360 // area and there are spots to guide the user experience.
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005361 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005362 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5363 } else {
5364 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5365 }
5366 break;
5367 }
5368
5369 // Send events!
5370 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01005371 int32_t buttonState = mCurrentCookedState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005372
5373 // Update last coordinates of pointers that have moved so that we observe the new
5374 // pointer positions at the same time as other pointers that have just gone up.
5375 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
5376 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
5377 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5378 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
5379 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
5380 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
5381 bool moveNeeded = false;
5382 if (down && !cancelPreviousGesture && !finishPreviousGesture
5383 && !mPointerGesture.lastGestureIdBits.isEmpty()
5384 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
5385 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
5386 & mPointerGesture.lastGestureIdBits.value);
5387 moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
5388 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5389 mPointerGesture.lastGestureProperties,
5390 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5391 movedGestureIdBits);
Michael Wright7b159c92015-05-14 14:48:03 +01005392 if (buttonState != mLastCookedState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005393 moveNeeded = true;
5394 }
5395 }
5396
5397 // Send motion events for all pointers that went up or were canceled.
5398 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
5399 if (!dispatchedGestureIdBits.isEmpty()) {
5400 if (cancelPreviousGesture) {
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005401 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
5402 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5403 mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
5404 mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
5405 mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005406
5407 dispatchedGestureIdBits.clear();
5408 } else {
5409 BitSet32 upGestureIdBits;
5410 if (finishPreviousGesture) {
5411 upGestureIdBits = dispatchedGestureIdBits;
5412 } else {
5413 upGestureIdBits.value = dispatchedGestureIdBits.value
5414 & ~mPointerGesture.currentGestureIdBits.value;
5415 }
5416 while (!upGestureIdBits.isEmpty()) {
5417 uint32_t id = upGestureIdBits.clearFirstMarkedBit();
5418
5419 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005420 AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005421 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5422 mPointerGesture.lastGestureProperties,
5423 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5424 dispatchedGestureIdBits, id,
5425 0, 0, mPointerGesture.downTime);
5426
5427 dispatchedGestureIdBits.clearBit(id);
5428 }
5429 }
5430 }
5431
5432 // Send motion events for all pointers that moved.
5433 if (moveNeeded) {
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005434 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
5435 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5436 mPointerGesture.currentGestureProperties,
5437 mPointerGesture.currentGestureCoords,
5438 mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
5439 mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005440 }
5441
5442 // Send motion events for all pointers that went down.
5443 if (down) {
5444 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
5445 & ~dispatchedGestureIdBits.value);
5446 while (!downGestureIdBits.isEmpty()) {
5447 uint32_t id = downGestureIdBits.clearFirstMarkedBit();
5448 dispatchedGestureIdBits.markBit(id);
5449
5450 if (dispatchedGestureIdBits.count() == 1) {
5451 mPointerGesture.downTime = when;
5452 }
5453
5454 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005455 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005456 mPointerGesture.currentGestureProperties,
5457 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5458 dispatchedGestureIdBits, id,
5459 0, 0, mPointerGesture.downTime);
5460 }
5461 }
5462
5463 // Send motion events for hover.
5464 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005465 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
5466 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5467 mPointerGesture.currentGestureProperties,
5468 mPointerGesture.currentGestureCoords,
5469 mPointerGesture.currentGestureIdToIndex,
5470 mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005471 } else if (dispatchedGestureIdBits.isEmpty()
5472 && !mPointerGesture.lastGestureIdBits.isEmpty()) {
5473 // Synthesize a hover move event after all pointers go up to indicate that
5474 // the pointer is hovering again even if the user is not currently touching
5475 // the touch pad. This ensures that a view will receive a fresh hover enter
5476 // event after a tap.
5477 float x, y;
5478 mPointerController->getPosition(&x, &y);
5479
5480 PointerProperties pointerProperties;
5481 pointerProperties.clear();
5482 pointerProperties.id = 0;
5483 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5484
5485 PointerCoords pointerCoords;
5486 pointerCoords.clear();
5487 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5488 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5489
Arthur Hungc7ad2d02018-12-18 17:41:29 +08005490 const int32_t displayId = mPointerController->getDisplayId();
Garfield Tan00f511d2019-06-12 16:55:40 -07005491 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
5492 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
5493 metaState, buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005494 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
5495 0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08005496 getListener()->notifyMotion(&args);
5497 }
5498
5499 // Update state.
5500 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
5501 if (!down) {
5502 mPointerGesture.lastGestureIdBits.clear();
5503 } else {
5504 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
5505 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
5506 uint32_t id = idBits.clearFirstMarkedBit();
5507 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
5508 mPointerGesture.lastGestureProperties[index].copyFrom(
5509 mPointerGesture.currentGestureProperties[index]);
5510 mPointerGesture.lastGestureCoords[index].copyFrom(
5511 mPointerGesture.currentGestureCoords[index]);
5512 mPointerGesture.lastGestureIdToIndex[id] = index;
5513 }
5514 }
5515}
5516
5517void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
5518 // Cancel previously dispatches pointers.
5519 if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
5520 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright842500e2015-03-13 17:32:02 -07005521 int32_t buttonState = mCurrentRawState.buttonState;
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005522 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
5523 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5524 mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
5525 mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
5526 0, 0, mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005527 }
5528
5529 // Reset the current pointer gesture.
5530 mPointerGesture.reset();
5531 mPointerVelocityControl.reset();
5532
5533 // Remove any current spots.
Yi Kong9b14ac62018-07-17 13:48:38 -07005534 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005535 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5536 mPointerController->clearSpots();
5537 }
5538}
5539
5540bool TouchInputMapper::preparePointerGestures(nsecs_t when,
5541 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
5542 *outCancelPreviousGesture = false;
5543 *outFinishPreviousGesture = false;
5544
5545 // Handle TAP timeout.
5546 if (isTimeout) {
5547#if DEBUG_GESTURES
5548 ALOGD("Gestures: Processing timeout");
5549#endif
5550
5551 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5552 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5553 // The tap/drag timeout has not yet expired.
5554 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
5555 + mConfig.pointerGestureTapDragInterval);
5556 } else {
5557 // The tap is finished.
5558#if DEBUG_GESTURES
5559 ALOGD("Gestures: TAP finished");
5560#endif
5561 *outFinishPreviousGesture = true;
5562
5563 mPointerGesture.activeGestureId = -1;
5564 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5565 mPointerGesture.currentGestureIdBits.clear();
5566
5567 mPointerVelocityControl.reset();
5568 return true;
5569 }
5570 }
5571
5572 // We did not handle this timeout.
5573 return false;
5574 }
5575
Michael Wright842500e2015-03-13 17:32:02 -07005576 const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
5577 const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005578
5579 // Update the velocity tracker.
5580 {
5581 VelocityTracker::Position positions[MAX_POINTERS];
5582 uint32_t count = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005583 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005584 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005585 const RawPointerData::Pointer& pointer =
5586 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005587 positions[count].x = pointer.x * mPointerXMovementScale;
5588 positions[count].y = pointer.y * mPointerYMovementScale;
5589 }
5590 mPointerGesture.velocityTracker.addMovement(when,
Michael Wright842500e2015-03-13 17:32:02 -07005591 mCurrentCookedState.fingerIdBits, positions);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005592 }
5593
5594 // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
5595 // to NEUTRAL, then we should not generate tap event.
5596 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
5597 && mPointerGesture.lastGestureMode != PointerGesture::TAP
5598 && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
5599 mPointerGesture.resetTap();
5600 }
5601
5602 // Pick a new active touch id if needed.
5603 // Choose an arbitrary pointer that just went down, if there is one.
5604 // Otherwise choose an arbitrary remaining pointer.
5605 // This guarantees we always have an active touch id when there is at least one pointer.
5606 // We keep the same active touch id for as long as possible.
Michael Wrightd02c5b62014-02-10 15:10:22 -08005607 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
5608 int32_t activeTouchId = lastActiveTouchId;
5609 if (activeTouchId < 0) {
Michael Wright842500e2015-03-13 17:32:02 -07005610 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005611 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07005612 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005613 mPointerGesture.firstTouchTime = when;
5614 }
Michael Wright842500e2015-03-13 17:32:02 -07005615 } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wright842500e2015-03-13 17:32:02 -07005616 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005617 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07005618 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005619 } else {
5620 activeTouchId = mPointerGesture.activeTouchId = -1;
5621 }
5622 }
5623
5624 // Determine whether we are in quiet time.
5625 bool isQuietTime = false;
5626 if (activeTouchId < 0) {
5627 mPointerGesture.resetQuietTime();
5628 } else {
5629 isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
5630 if (!isQuietTime) {
5631 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
5632 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
5633 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
5634 && currentFingerCount < 2) {
5635 // Enter quiet time when exiting swipe or freeform state.
5636 // This is to prevent accidentally entering the hover state and flinging the
5637 // pointer when finishing a swipe and there is still one pointer left onscreen.
5638 isQuietTime = true;
5639 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5640 && currentFingerCount >= 2
Michael Wright842500e2015-03-13 17:32:02 -07005641 && !isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005642 // Enter quiet time when releasing the button and there are still two or more
5643 // fingers down. This may indicate that one finger was used to press the button
5644 // but it has not gone up yet.
5645 isQuietTime = true;
5646 }
5647 if (isQuietTime) {
5648 mPointerGesture.quietTime = when;
5649 }
5650 }
5651 }
5652
5653 // Switch states based on button and pointer state.
5654 if (isQuietTime) {
5655 // Case 1: Quiet time. (QUIET)
5656#if DEBUG_GESTURES
5657 ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
5658 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
5659#endif
5660 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
5661 *outFinishPreviousGesture = true;
5662 }
5663
5664 mPointerGesture.activeGestureId = -1;
5665 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
5666 mPointerGesture.currentGestureIdBits.clear();
5667
5668 mPointerVelocityControl.reset();
Michael Wright842500e2015-03-13 17:32:02 -07005669 } else if (isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005670 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
5671 // The pointer follows the active touch point.
5672 // Emit DOWN, MOVE, UP events at the pointer location.
5673 //
5674 // Only the active touch matters; other fingers are ignored. This policy helps
5675 // to handle the case where the user places a second finger on the touch pad
5676 // to apply the necessary force to depress an integrated button below the surface.
5677 // We don't want the second finger to be delivered to applications.
5678 //
5679 // For this to work well, we need to make sure to track the pointer that is really
5680 // active. If the user first puts one finger down to click then adds another
5681 // finger to drag then the active pointer should switch to the finger that is
5682 // being dragged.
5683#if DEBUG_GESTURES
5684 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
5685 "currentFingerCount=%d", activeTouchId, currentFingerCount);
5686#endif
5687 // Reset state when just starting.
5688 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
5689 *outFinishPreviousGesture = true;
5690 mPointerGesture.activeGestureId = 0;
5691 }
5692
5693 // Switch pointers if needed.
5694 // Find the fastest pointer and follow it.
5695 if (activeTouchId >= 0 && currentFingerCount > 1) {
5696 int32_t bestId = -1;
5697 float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
Michael Wright842500e2015-03-13 17:32:02 -07005698 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005699 uint32_t id = idBits.clearFirstMarkedBit();
5700 float vx, vy;
5701 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
5702 float speed = hypotf(vx, vy);
5703 if (speed > bestSpeed) {
5704 bestId = id;
5705 bestSpeed = speed;
5706 }
5707 }
5708 }
5709 if (bestId >= 0 && bestId != activeTouchId) {
5710 mPointerGesture.activeTouchId = activeTouchId = bestId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005711#if DEBUG_GESTURES
5712 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
5713 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
5714#endif
5715 }
5716 }
5717
Jun Mukaifa1706a2015-12-03 01:14:46 -08005718 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005719 if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005720 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005721 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005722 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005723 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Jun Mukaifa1706a2015-12-03 01:14:46 -08005724 deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5725 deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005726
5727 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5728 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5729
5730 // Move the pointer using a relative motion.
5731 // When using spots, the click will occur at the position of the anchor
5732 // spot and all other spots will move there.
5733 mPointerController->move(deltaX, deltaY);
5734 } else {
5735 mPointerVelocityControl.reset();
5736 }
5737
5738 float x, y;
5739 mPointerController->getPosition(&x, &y);
5740
5741 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
5742 mPointerGesture.currentGestureIdBits.clear();
5743 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5744 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5745 mPointerGesture.currentGestureProperties[0].clear();
5746 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5747 mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5748 mPointerGesture.currentGestureCoords[0].clear();
5749 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5750 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5751 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5752 } else if (currentFingerCount == 0) {
5753 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
5754 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
5755 *outFinishPreviousGesture = true;
5756 }
5757
5758 // Watch for taps coming out of HOVER or TAP_DRAG mode.
5759 // Checking for taps after TAP_DRAG allows us to detect double-taps.
5760 bool tapped = false;
5761 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
5762 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
5763 && lastFingerCount == 1) {
5764 if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
5765 float x, y;
5766 mPointerController->getPosition(&x, &y);
5767 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5768 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5769#if DEBUG_GESTURES
5770 ALOGD("Gestures: TAP");
5771#endif
5772
5773 mPointerGesture.tapUpTime = when;
5774 getContext()->requestTimeoutAtTime(when
5775 + mConfig.pointerGestureTapDragInterval);
5776
5777 mPointerGesture.activeGestureId = 0;
5778 mPointerGesture.currentGestureMode = PointerGesture::TAP;
5779 mPointerGesture.currentGestureIdBits.clear();
5780 mPointerGesture.currentGestureIdBits.markBit(
5781 mPointerGesture.activeGestureId);
5782 mPointerGesture.currentGestureIdToIndex[
5783 mPointerGesture.activeGestureId] = 0;
5784 mPointerGesture.currentGestureProperties[0].clear();
5785 mPointerGesture.currentGestureProperties[0].id =
5786 mPointerGesture.activeGestureId;
5787 mPointerGesture.currentGestureProperties[0].toolType =
5788 AMOTION_EVENT_TOOL_TYPE_FINGER;
5789 mPointerGesture.currentGestureCoords[0].clear();
5790 mPointerGesture.currentGestureCoords[0].setAxisValue(
5791 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
5792 mPointerGesture.currentGestureCoords[0].setAxisValue(
5793 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
5794 mPointerGesture.currentGestureCoords[0].setAxisValue(
5795 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5796
5797 tapped = true;
5798 } else {
5799#if DEBUG_GESTURES
5800 ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
5801 x - mPointerGesture.tapX,
5802 y - mPointerGesture.tapY);
5803#endif
5804 }
5805 } else {
5806#if DEBUG_GESTURES
5807 if (mPointerGesture.tapDownTime != LLONG_MIN) {
5808 ALOGD("Gestures: Not a TAP, %0.3fms since down",
5809 (when - mPointerGesture.tapDownTime) * 0.000001f);
5810 } else {
5811 ALOGD("Gestures: Not a TAP, incompatible mode transitions");
5812 }
5813#endif
5814 }
5815 }
5816
5817 mPointerVelocityControl.reset();
5818
5819 if (!tapped) {
5820#if DEBUG_GESTURES
5821 ALOGD("Gestures: NEUTRAL");
5822#endif
5823 mPointerGesture.activeGestureId = -1;
5824 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5825 mPointerGesture.currentGestureIdBits.clear();
5826 }
5827 } else if (currentFingerCount == 1) {
5828 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
5829 // The pointer follows the active touch point.
5830 // When in HOVER, emit HOVER_MOVE events at the pointer location.
5831 // When in TAP_DRAG, emit MOVE events at the pointer location.
5832 ALOG_ASSERT(activeTouchId >= 0);
5833
5834 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
5835 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5836 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5837 float x, y;
5838 mPointerController->getPosition(&x, &y);
5839 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5840 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5841 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5842 } else {
5843#if DEBUG_GESTURES
5844 ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
5845 x - mPointerGesture.tapX,
5846 y - mPointerGesture.tapY);
5847#endif
5848 }
5849 } else {
5850#if DEBUG_GESTURES
5851 ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
5852 (when - mPointerGesture.tapUpTime) * 0.000001f);
5853#endif
5854 }
5855 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
5856 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5857 }
5858
Jun Mukaifa1706a2015-12-03 01:14:46 -08005859 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005860 if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005861 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005862 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005863 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005864 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Jun Mukaifa1706a2015-12-03 01:14:46 -08005865 deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5866 deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005867
5868 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5869 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5870
5871 // Move the pointer using a relative motion.
5872 // When using spots, the hover or drag will occur at the position of the anchor spot.
5873 mPointerController->move(deltaX, deltaY);
5874 } else {
5875 mPointerVelocityControl.reset();
5876 }
5877
5878 bool down;
5879 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
5880#if DEBUG_GESTURES
5881 ALOGD("Gestures: TAP_DRAG");
5882#endif
5883 down = true;
5884 } else {
5885#if DEBUG_GESTURES
5886 ALOGD("Gestures: HOVER");
5887#endif
5888 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
5889 *outFinishPreviousGesture = true;
5890 }
5891 mPointerGesture.activeGestureId = 0;
5892 down = false;
5893 }
5894
5895 float x, y;
5896 mPointerController->getPosition(&x, &y);
5897
5898 mPointerGesture.currentGestureIdBits.clear();
5899 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5900 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5901 mPointerGesture.currentGestureProperties[0].clear();
5902 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5903 mPointerGesture.currentGestureProperties[0].toolType =
5904 AMOTION_EVENT_TOOL_TYPE_FINGER;
5905 mPointerGesture.currentGestureCoords[0].clear();
5906 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5907 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5908 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5909 down ? 1.0f : 0.0f);
5910
5911 if (lastFingerCount == 0 && currentFingerCount != 0) {
5912 mPointerGesture.resetTap();
5913 mPointerGesture.tapDownTime = when;
5914 mPointerGesture.tapX = x;
5915 mPointerGesture.tapY = y;
5916 }
5917 } else {
5918 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
5919 // We need to provide feedback for each finger that goes down so we cannot wait
5920 // for the fingers to move before deciding what to do.
5921 //
5922 // The ambiguous case is deciding what to do when there are two fingers down but they
5923 // have not moved enough to determine whether they are part of a drag or part of a
5924 // freeform gesture, or just a press or long-press at the pointer location.
5925 //
5926 // When there are two fingers we start with the PRESS hypothesis and we generate a
5927 // down at the pointer location.
5928 //
5929 // When the two fingers move enough or when additional fingers are added, we make
5930 // a decision to transition into SWIPE or FREEFORM mode accordingly.
5931 ALOG_ASSERT(activeTouchId >= 0);
5932
5933 bool settled = when >= mPointerGesture.firstTouchTime
5934 + mConfig.pointerGestureMultitouchSettleInterval;
5935 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
5936 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
5937 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5938 *outFinishPreviousGesture = true;
5939 } else if (!settled && currentFingerCount > lastFingerCount) {
5940 // Additional pointers have gone down but not yet settled.
5941 // Reset the gesture.
5942#if DEBUG_GESTURES
5943 ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
5944 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5945 + mConfig.pointerGestureMultitouchSettleInterval - when)
5946 * 0.000001f);
5947#endif
5948 *outCancelPreviousGesture = true;
5949 } else {
5950 // Continue previous gesture.
5951 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
5952 }
5953
5954 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
5955 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
5956 mPointerGesture.activeGestureId = 0;
5957 mPointerGesture.referenceIdBits.clear();
5958 mPointerVelocityControl.reset();
5959
5960 // Use the centroid and pointer location as the reference points for the gesture.
5961#if DEBUG_GESTURES
5962 ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
5963 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5964 + mConfig.pointerGestureMultitouchSettleInterval - when)
5965 * 0.000001f);
5966#endif
Michael Wright842500e2015-03-13 17:32:02 -07005967 mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
Michael Wrightd02c5b62014-02-10 15:10:22 -08005968 &mPointerGesture.referenceTouchX,
5969 &mPointerGesture.referenceTouchY);
5970 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
5971 &mPointerGesture.referenceGestureY);
5972 }
5973
5974 // Clear the reference deltas for fingers not yet included in the reference calculation.
Michael Wright842500e2015-03-13 17:32:02 -07005975 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
Michael Wrightd02c5b62014-02-10 15:10:22 -08005976 & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
5977 uint32_t id = idBits.clearFirstMarkedBit();
5978 mPointerGesture.referenceDeltas[id].dx = 0;
5979 mPointerGesture.referenceDeltas[id].dy = 0;
5980 }
Michael Wright842500e2015-03-13 17:32:02 -07005981 mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005982
5983 // Add delta for all fingers and calculate a common movement delta.
5984 float commonDeltaX = 0, commonDeltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005985 BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
5986 & mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005987 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
5988 bool first = (idBits == commonIdBits);
5989 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005990 const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
5991 const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005992 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5993 delta.dx += cpd.x - lpd.x;
5994 delta.dy += cpd.y - lpd.y;
5995
5996 if (first) {
5997 commonDeltaX = delta.dx;
5998 commonDeltaY = delta.dy;
5999 } else {
6000 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
6001 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
6002 }
6003 }
6004
6005 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
6006 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
6007 float dist[MAX_POINTER_ID + 1];
6008 int32_t distOverThreshold = 0;
6009 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
6010 uint32_t id = idBits.clearFirstMarkedBit();
6011 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
6012 dist[id] = hypotf(delta.dx * mPointerXZoomScale,
6013 delta.dy * mPointerYZoomScale);
6014 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
6015 distOverThreshold += 1;
6016 }
6017 }
6018
6019 // Only transition when at least two pointers have moved further than
6020 // the minimum distance threshold.
6021 if (distOverThreshold >= 2) {
6022 if (currentFingerCount > 2) {
6023 // There are more than two pointers, switch to FREEFORM.
6024#if DEBUG_GESTURES
6025 ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
6026 currentFingerCount);
6027#endif
6028 *outCancelPreviousGesture = true;
6029 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6030 } else {
6031 // There are exactly two pointers.
Michael Wright842500e2015-03-13 17:32:02 -07006032 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006033 uint32_t id1 = idBits.clearFirstMarkedBit();
6034 uint32_t id2 = idBits.firstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07006035 const RawPointerData::Pointer& p1 =
6036 mCurrentRawState.rawPointerData.pointerForId(id1);
6037 const RawPointerData::Pointer& p2 =
6038 mCurrentRawState.rawPointerData.pointerForId(id2);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006039 float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
6040 if (mutualDistance > mPointerGestureMaxSwipeWidth) {
6041 // There are two pointers but they are too far apart for a SWIPE,
6042 // switch to FREEFORM.
6043#if DEBUG_GESTURES
6044 ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
6045 mutualDistance, mPointerGestureMaxSwipeWidth);
6046#endif
6047 *outCancelPreviousGesture = true;
6048 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6049 } else {
6050 // There are two pointers. Wait for both pointers to start moving
6051 // before deciding whether this is a SWIPE or FREEFORM gesture.
6052 float dist1 = dist[id1];
6053 float dist2 = dist[id2];
6054 if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
6055 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
6056 // Calculate the dot product of the displacement vectors.
6057 // When the vectors are oriented in approximately the same direction,
6058 // the angle betweeen them is near zero and the cosine of the angle
6059 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
6060 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
6061 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
6062 float dx1 = delta1.dx * mPointerXZoomScale;
6063 float dy1 = delta1.dy * mPointerYZoomScale;
6064 float dx2 = delta2.dx * mPointerXZoomScale;
6065 float dy2 = delta2.dy * mPointerYZoomScale;
6066 float dot = dx1 * dx2 + dy1 * dy2;
6067 float cosine = dot / (dist1 * dist2); // denominator always > 0
6068 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
6069 // Pointers are moving in the same direction. Switch to SWIPE.
6070#if DEBUG_GESTURES
6071 ALOGD("Gestures: PRESS transitioned to SWIPE, "
6072 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
6073 "cosine %0.3f >= %0.3f",
6074 dist1, mConfig.pointerGestureMultitouchMinDistance,
6075 dist2, mConfig.pointerGestureMultitouchMinDistance,
6076 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
6077#endif
6078 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
6079 } else {
6080 // Pointers are moving in different directions. Switch to FREEFORM.
6081#if DEBUG_GESTURES
6082 ALOGD("Gestures: PRESS transitioned to FREEFORM, "
6083 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
6084 "cosine %0.3f < %0.3f",
6085 dist1, mConfig.pointerGestureMultitouchMinDistance,
6086 dist2, mConfig.pointerGestureMultitouchMinDistance,
6087 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
6088#endif
6089 *outCancelPreviousGesture = true;
6090 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6091 }
6092 }
6093 }
6094 }
6095 }
6096 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
6097 // Switch from SWIPE to FREEFORM if additional pointers go down.
6098 // Cancel previous gesture.
6099 if (currentFingerCount > 2) {
6100#if DEBUG_GESTURES
6101 ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
6102 currentFingerCount);
6103#endif
6104 *outCancelPreviousGesture = true;
6105 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6106 }
6107 }
6108
6109 // Move the reference points based on the overall group motion of the fingers
6110 // except in PRESS mode while waiting for a transition to occur.
6111 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
6112 && (commonDeltaX || commonDeltaY)) {
6113 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
6114 uint32_t id = idBits.clearFirstMarkedBit();
6115 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
6116 delta.dx = 0;
6117 delta.dy = 0;
6118 }
6119
6120 mPointerGesture.referenceTouchX += commonDeltaX;
6121 mPointerGesture.referenceTouchY += commonDeltaY;
6122
6123 commonDeltaX *= mPointerXMovementScale;
6124 commonDeltaY *= mPointerYMovementScale;
6125
6126 rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
6127 mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
6128
6129 mPointerGesture.referenceGestureX += commonDeltaX;
6130 mPointerGesture.referenceGestureY += commonDeltaY;
6131 }
6132
6133 // Report gestures.
6134 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
6135 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
6136 // PRESS or SWIPE mode.
6137#if DEBUG_GESTURES
6138 ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
6139 "activeGestureId=%d, currentTouchPointerCount=%d",
6140 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
6141#endif
6142 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
6143
6144 mPointerGesture.currentGestureIdBits.clear();
6145 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
6146 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
6147 mPointerGesture.currentGestureProperties[0].clear();
6148 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
6149 mPointerGesture.currentGestureProperties[0].toolType =
6150 AMOTION_EVENT_TOOL_TYPE_FINGER;
6151 mPointerGesture.currentGestureCoords[0].clear();
6152 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6153 mPointerGesture.referenceGestureX);
6154 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
6155 mPointerGesture.referenceGestureY);
6156 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
6157 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
6158 // FREEFORM mode.
6159#if DEBUG_GESTURES
6160 ALOGD("Gestures: FREEFORM activeTouchId=%d,"
6161 "activeGestureId=%d, currentTouchPointerCount=%d",
6162 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
6163#endif
6164 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
6165
6166 mPointerGesture.currentGestureIdBits.clear();
6167
6168 BitSet32 mappedTouchIdBits;
6169 BitSet32 usedGestureIdBits;
6170 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
6171 // Initially, assign the active gesture id to the active touch point
6172 // if there is one. No other touch id bits are mapped yet.
6173 if (!*outCancelPreviousGesture) {
6174 mappedTouchIdBits.markBit(activeTouchId);
6175 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
6176 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
6177 mPointerGesture.activeGestureId;
6178 } else {
6179 mPointerGesture.activeGestureId = -1;
6180 }
6181 } else {
6182 // Otherwise, assume we mapped all touches from the previous frame.
6183 // Reuse all mappings that are still applicable.
Michael Wright842500e2015-03-13 17:32:02 -07006184 mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
6185 & mCurrentCookedState.fingerIdBits.value;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006186 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
6187
6188 // Check whether we need to choose a new active gesture id because the
6189 // current went went up.
Michael Wright842500e2015-03-13 17:32:02 -07006190 for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
6191 & ~mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006192 !upTouchIdBits.isEmpty(); ) {
6193 uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
6194 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
6195 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
6196 mPointerGesture.activeGestureId = -1;
6197 break;
6198 }
6199 }
6200 }
6201
6202#if DEBUG_GESTURES
6203 ALOGD("Gestures: FREEFORM follow up "
6204 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
6205 "activeGestureId=%d",
6206 mappedTouchIdBits.value, usedGestureIdBits.value,
6207 mPointerGesture.activeGestureId);
6208#endif
6209
Michael Wright842500e2015-03-13 17:32:02 -07006210 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006211 for (uint32_t i = 0; i < currentFingerCount; i++) {
6212 uint32_t touchId = idBits.clearFirstMarkedBit();
6213 uint32_t gestureId;
6214 if (!mappedTouchIdBits.hasBit(touchId)) {
6215 gestureId = usedGestureIdBits.markFirstUnmarkedBit();
6216 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
6217#if DEBUG_GESTURES
6218 ALOGD("Gestures: FREEFORM "
6219 "new mapping for touch id %d -> gesture id %d",
6220 touchId, gestureId);
6221#endif
6222 } else {
6223 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
6224#if DEBUG_GESTURES
6225 ALOGD("Gestures: FREEFORM "
6226 "existing mapping for touch id %d -> gesture id %d",
6227 touchId, gestureId);
6228#endif
6229 }
6230 mPointerGesture.currentGestureIdBits.markBit(gestureId);
6231 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
6232
6233 const RawPointerData::Pointer& pointer =
Michael Wright842500e2015-03-13 17:32:02 -07006234 mCurrentRawState.rawPointerData.pointerForId(touchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006235 float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
6236 * mPointerXZoomScale;
6237 float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
6238 * mPointerYZoomScale;
6239 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
6240
6241 mPointerGesture.currentGestureProperties[i].clear();
6242 mPointerGesture.currentGestureProperties[i].id = gestureId;
6243 mPointerGesture.currentGestureProperties[i].toolType =
6244 AMOTION_EVENT_TOOL_TYPE_FINGER;
6245 mPointerGesture.currentGestureCoords[i].clear();
6246 mPointerGesture.currentGestureCoords[i].setAxisValue(
6247 AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
6248 mPointerGesture.currentGestureCoords[i].setAxisValue(
6249 AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
6250 mPointerGesture.currentGestureCoords[i].setAxisValue(
6251 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
6252 }
6253
6254 if (mPointerGesture.activeGestureId < 0) {
6255 mPointerGesture.activeGestureId =
6256 mPointerGesture.currentGestureIdBits.firstMarkedBit();
6257#if DEBUG_GESTURES
6258 ALOGD("Gestures: FREEFORM new "
6259 "activeGestureId=%d", mPointerGesture.activeGestureId);
6260#endif
6261 }
6262 }
6263 }
6264
Michael Wright842500e2015-03-13 17:32:02 -07006265 mPointerController->setButtonState(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006266
6267#if DEBUG_GESTURES
6268 ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
6269 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
6270 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
6271 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
6272 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
6273 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
6274 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
6275 uint32_t id = idBits.clearFirstMarkedBit();
6276 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
6277 const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
6278 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
6279 ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
6280 "x=%0.3f, y=%0.3f, pressure=%0.3f",
6281 id, index, properties.toolType,
6282 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
6283 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
6284 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
6285 }
6286 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
6287 uint32_t id = idBits.clearFirstMarkedBit();
6288 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
6289 const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
6290 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
6291 ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
6292 "x=%0.3f, y=%0.3f, pressure=%0.3f",
6293 id, index, properties.toolType,
6294 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
6295 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
6296 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
6297 }
6298#endif
6299 return true;
6300}
6301
6302void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
6303 mPointerSimple.currentCoords.clear();
6304 mPointerSimple.currentProperties.clear();
6305
6306 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07006307 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
6308 uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
6309 uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
6310 float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
6311 float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006312 mPointerController->setPosition(x, y);
6313
Michael Wright842500e2015-03-13 17:32:02 -07006314 hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006315 down = !hovering;
6316
6317 mPointerController->getPosition(&x, &y);
Michael Wright842500e2015-03-13 17:32:02 -07006318 mPointerSimple.currentCoords.copyFrom(
6319 mCurrentCookedState.cookedPointerData.pointerCoords[index]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006320 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
6321 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
6322 mPointerSimple.currentProperties.id = 0;
6323 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07006324 mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006325 } else {
6326 down = false;
6327 hovering = false;
6328 }
6329
6330 dispatchPointerSimple(when, policyFlags, down, hovering);
6331}
6332
6333void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
6334 abortPointerSimple(when, policyFlags);
6335}
6336
6337void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
6338 mPointerSimple.currentCoords.clear();
6339 mPointerSimple.currentProperties.clear();
6340
6341 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07006342 if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
6343 uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
6344 uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
Jun Mukaifa1706a2015-12-03 01:14:46 -08006345 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07006346 if (mLastCookedState.mouseIdBits.hasBit(id)) {
6347 uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
Jun Mukaifa1706a2015-12-03 01:14:46 -08006348 deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
Michael Wright842500e2015-03-13 17:32:02 -07006349 - mLastRawState.rawPointerData.pointers[lastIndex].x)
Michael Wrightd02c5b62014-02-10 15:10:22 -08006350 * mPointerXMovementScale;
Jun Mukaifa1706a2015-12-03 01:14:46 -08006351 deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
Michael Wright842500e2015-03-13 17:32:02 -07006352 - mLastRawState.rawPointerData.pointers[lastIndex].y)
Michael Wrightd02c5b62014-02-10 15:10:22 -08006353 * mPointerYMovementScale;
6354
6355 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
6356 mPointerVelocityControl.move(when, &deltaX, &deltaY);
6357
6358 mPointerController->move(deltaX, deltaY);
6359 } else {
6360 mPointerVelocityControl.reset();
6361 }
6362
Michael Wright842500e2015-03-13 17:32:02 -07006363 down = isPointerDown(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006364 hovering = !down;
6365
6366 float x, y;
6367 mPointerController->getPosition(&x, &y);
6368 mPointerSimple.currentCoords.copyFrom(
Michael Wright842500e2015-03-13 17:32:02 -07006369 mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006370 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
6371 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
6372 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
6373 hovering ? 0.0f : 1.0f);
6374 mPointerSimple.currentProperties.id = 0;
6375 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07006376 mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006377 } else {
6378 mPointerVelocityControl.reset();
6379
6380 down = false;
6381 hovering = false;
6382 }
6383
6384 dispatchPointerSimple(when, policyFlags, down, hovering);
6385}
6386
6387void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
6388 abortPointerSimple(when, policyFlags);
6389
6390 mPointerVelocityControl.reset();
6391}
6392
6393void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
6394 bool down, bool hovering) {
6395 int32_t metaState = getContext()->getGlobalMetaState();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08006396 int32_t displayId = mViewport.displayId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006397
Garfield Tan00f511d2019-06-12 16:55:40 -07006398 if (down || hovering) {
6399 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
6400 mPointerController->clearSpots();
6401 mPointerController->setButtonState(mCurrentRawState.buttonState);
6402 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
6403 } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
6404 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006405 }
Garfield Tan00f511d2019-06-12 16:55:40 -07006406 displayId = mPointerController->getDisplayId();
6407
6408 float xCursorPosition;
6409 float yCursorPosition;
6410 mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006411
6412 if (mPointerSimple.down && !down) {
6413 mPointerSimple.down = false;
6414
6415 // Send up.
Garfield Tan00f511d2019-06-12 16:55:40 -07006416 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6417 displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
6418 mLastRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006419 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
6420 &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
6421 xCursorPosition, yCursorPosition, mPointerSimple.downTime,
6422 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006423 getListener()->notifyMotion(&args);
6424 }
6425
6426 if (mPointerSimple.hovering && !hovering) {
6427 mPointerSimple.hovering = false;
6428
6429 // Send hover exit.
Garfield Tan00f511d2019-06-12 16:55:40 -07006430 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6431 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
6432 metaState, mLastRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006433 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
6434 &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
6435 xCursorPosition, yCursorPosition, mPointerSimple.downTime,
6436 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006437 getListener()->notifyMotion(&args);
6438 }
6439
6440 if (down) {
6441 if (!mPointerSimple.down) {
6442 mPointerSimple.down = true;
6443 mPointerSimple.downTime = when;
6444
6445 // Send down.
Garfield Tan00f511d2019-06-12 16:55:40 -07006446 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6447 displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6448 metaState, mCurrentRawState.buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006449 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
6450 &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6451 mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
6452 yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006453 getListener()->notifyMotion(&args);
6454 }
6455
6456 // Send move.
Garfield Tan00f511d2019-06-12 16:55:40 -07006457 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6458 displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
6459 mCurrentRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006460 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
6461 &mPointerSimple.currentCoords, mOrientedXPrecision,
6462 mOrientedYPrecision, xCursorPosition, yCursorPosition,
6463 mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006464 getListener()->notifyMotion(&args);
6465 }
6466
6467 if (hovering) {
6468 if (!mPointerSimple.hovering) {
6469 mPointerSimple.hovering = true;
6470
6471 // Send hover enter.
Garfield Tan00f511d2019-06-12 16:55:40 -07006472 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6473 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
6474 metaState, mCurrentRawState.buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006475 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
6476 &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6477 mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
6478 yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006479 getListener()->notifyMotion(&args);
6480 }
6481
6482 // Send hover move.
Garfield Tan00f511d2019-06-12 16:55:40 -07006483 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6484 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
6485 metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006486 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
6487 &mPointerSimple.currentCoords, mOrientedXPrecision,
6488 mOrientedYPrecision, xCursorPosition, yCursorPosition,
6489 mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006490 getListener()->notifyMotion(&args);
6491 }
6492
Michael Wright842500e2015-03-13 17:32:02 -07006493 if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
6494 float vscroll = mCurrentRawState.rawVScroll;
6495 float hscroll = mCurrentRawState.rawHScroll;
Yi Kong9b14ac62018-07-17 13:48:38 -07006496 mWheelYVelocityControl.move(when, nullptr, &vscroll);
6497 mWheelXVelocityControl.move(when, &hscroll, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006498
6499 // Send scroll.
6500 PointerCoords pointerCoords;
6501 pointerCoords.copyFrom(mPointerSimple.currentCoords);
6502 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
6503 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
6504
Garfield Tan00f511d2019-06-12 16:55:40 -07006505 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6506 displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
6507 mCurrentRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006508 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
6509 &pointerCoords, mOrientedXPrecision, mOrientedYPrecision,
6510 xCursorPosition, yCursorPosition, mPointerSimple.downTime,
6511 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006512 getListener()->notifyMotion(&args);
6513 }
6514
6515 // Save state.
6516 if (down || hovering) {
6517 mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
6518 mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
6519 } else {
6520 mPointerSimple.reset();
6521 }
6522}
6523
6524void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
6525 mPointerSimple.currentCoords.clear();
6526 mPointerSimple.currentProperties.clear();
6527
6528 dispatchPointerSimple(when, policyFlags, false, false);
6529}
6530
6531void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006532 int32_t action, int32_t actionButton, int32_t flags,
6533 int32_t metaState, int32_t buttonState, int32_t edgeFlags,
6534 const PointerProperties* properties,
6535 const PointerCoords* coords, const uint32_t* idToIndex,
6536 BitSet32 idBits, int32_t changedId, float xPrecision,
6537 float yPrecision, nsecs_t downTime) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006538 PointerCoords pointerCoords[MAX_POINTERS];
6539 PointerProperties pointerProperties[MAX_POINTERS];
6540 uint32_t pointerCount = 0;
6541 while (!idBits.isEmpty()) {
6542 uint32_t id = idBits.clearFirstMarkedBit();
6543 uint32_t index = idToIndex[id];
6544 pointerProperties[pointerCount].copyFrom(properties[index]);
6545 pointerCoords[pointerCount].copyFrom(coords[index]);
6546
6547 if (changedId >= 0 && id == uint32_t(changedId)) {
6548 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
6549 }
6550
6551 pointerCount += 1;
6552 }
6553
6554 ALOG_ASSERT(pointerCount != 0);
6555
6556 if (changedId >= 0 && pointerCount == 1) {
6557 // Replace initial down and final up action.
6558 // We can compare the action without masking off the changed pointer index
6559 // because we know the index is 0.
6560 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
6561 action = AMOTION_EVENT_ACTION_DOWN;
6562 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
6563 action = AMOTION_EVENT_ACTION_UP;
6564 } else {
6565 // Can't happen.
6566 ALOG_ASSERT(false);
6567 }
6568 }
Garfield Tan00f511d2019-06-12 16:55:40 -07006569 float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
6570 float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
6571 if (mDeviceMode == DEVICE_MODE_POINTER) {
6572 mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
6573 }
Arthur Hung2c9a3342019-07-23 14:18:59 +08006574 const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
Siarhei Vishniakouadd89292018-12-13 19:23:36 -08006575 const int32_t deviceId = getDeviceId();
6576 std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06006577 std::for_each(frames.begin(), frames.end(),
6578 [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
Garfield Tan00f511d2019-06-12 16:55:40 -07006579 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, displayId,
6580 policyFlags, action, actionButton, flags, metaState, buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006581 MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
6582 pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
6583 downTime, std::move(frames));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006584 getListener()->notifyMotion(&args);
6585}
6586
6587bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
6588 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
6589 PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
6590 BitSet32 idBits) const {
6591 bool changed = false;
6592 while (!idBits.isEmpty()) {
6593 uint32_t id = idBits.clearFirstMarkedBit();
6594 uint32_t inIndex = inIdToIndex[id];
6595 uint32_t outIndex = outIdToIndex[id];
6596
6597 const PointerProperties& curInProperties = inProperties[inIndex];
6598 const PointerCoords& curInCoords = inCoords[inIndex];
6599 PointerProperties& curOutProperties = outProperties[outIndex];
6600 PointerCoords& curOutCoords = outCoords[outIndex];
6601
6602 if (curInProperties != curOutProperties) {
6603 curOutProperties.copyFrom(curInProperties);
6604 changed = true;
6605 }
6606
6607 if (curInCoords != curOutCoords) {
6608 curOutCoords.copyFrom(curInCoords);
6609 changed = true;
6610 }
6611 }
6612 return changed;
6613}
6614
6615void TouchInputMapper::fadePointer() {
Yi Kong9b14ac62018-07-17 13:48:38 -07006616 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006617 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
6618 }
6619}
6620
Jeff Brownc9aa6282015-02-11 19:03:28 -08006621void TouchInputMapper::cancelTouch(nsecs_t when) {
6622 abortPointerUsage(when, 0 /*policyFlags*/);
Michael Wright8e812822015-06-22 16:18:21 +01006623 abortTouches(when, 0 /* policyFlags*/);
Jeff Brownc9aa6282015-02-11 19:03:28 -08006624}
6625
Michael Wrightd02c5b62014-02-10 15:10:22 -08006626bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
Michael Wright358bcc72018-08-21 04:01:07 +01006627 const float scaledX = x * mXScale;
Michael Wrightc597d612018-08-22 13:49:32 +01006628 const float scaledY = y * mYScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006629 return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
Michael Wright358bcc72018-08-21 04:01:07 +01006630 && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
6631 && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
6632 && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006633}
6634
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006635const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006636
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006637 for (const VirtualKey& virtualKey: mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006638#if DEBUG_VIRTUAL_KEYS
6639 ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
6640 "left=%d, top=%d, right=%d, bottom=%d",
6641 x, y,
6642 virtualKey.keyCode, virtualKey.scanCode,
6643 virtualKey.hitLeft, virtualKey.hitTop,
6644 virtualKey.hitRight, virtualKey.hitBottom);
6645#endif
6646
6647 if (virtualKey.isHit(x, y)) {
6648 return & virtualKey;
6649 }
6650 }
6651
Yi Kong9b14ac62018-07-17 13:48:38 -07006652 return nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006653}
6654
Michael Wright842500e2015-03-13 17:32:02 -07006655void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
6656 uint32_t currentPointerCount = current->rawPointerData.pointerCount;
6657 uint32_t lastPointerCount = last->rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006658
Michael Wright842500e2015-03-13 17:32:02 -07006659 current->rawPointerData.clearIdBits();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006660
6661 if (currentPointerCount == 0) {
6662 // No pointers to assign.
6663 return;
6664 }
6665
6666 if (lastPointerCount == 0) {
6667 // All pointers are new.
6668 for (uint32_t i = 0; i < currentPointerCount; i++) {
6669 uint32_t id = i;
Michael Wright842500e2015-03-13 17:32:02 -07006670 current->rawPointerData.pointers[i].id = id;
6671 current->rawPointerData.idToIndex[id] = i;
6672 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006673 }
6674 return;
6675 }
6676
6677 if (currentPointerCount == 1 && lastPointerCount == 1
Michael Wright842500e2015-03-13 17:32:02 -07006678 && current->rawPointerData.pointers[0].toolType
6679 == last->rawPointerData.pointers[0].toolType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006680 // Only one pointer and no change in count so it must have the same id as before.
Michael Wright842500e2015-03-13 17:32:02 -07006681 uint32_t id = last->rawPointerData.pointers[0].id;
6682 current->rawPointerData.pointers[0].id = id;
6683 current->rawPointerData.idToIndex[id] = 0;
6684 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006685 return;
6686 }
6687
6688 // General case.
6689 // We build a heap of squared euclidean distances between current and last pointers
6690 // associated with the current and last pointer indices. Then, we find the best
6691 // match (by distance) for each current pointer.
6692 // The pointers must have the same tool type but it is possible for them to
6693 // transition from hovering to touching or vice-versa while retaining the same id.
6694 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
6695
6696 uint32_t heapSize = 0;
6697 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
6698 currentPointerIndex++) {
6699 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
6700 lastPointerIndex++) {
6701 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006702 current->rawPointerData.pointers[currentPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006703 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006704 last->rawPointerData.pointers[lastPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006705 if (currentPointer.toolType == lastPointer.toolType) {
6706 int64_t deltaX = currentPointer.x - lastPointer.x;
6707 int64_t deltaY = currentPointer.y - lastPointer.y;
6708
6709 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
6710
6711 // Insert new element into the heap (sift up).
6712 heap[heapSize].currentPointerIndex = currentPointerIndex;
6713 heap[heapSize].lastPointerIndex = lastPointerIndex;
6714 heap[heapSize].distance = distance;
6715 heapSize += 1;
6716 }
6717 }
6718 }
6719
6720 // Heapify
6721 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
6722 startIndex -= 1;
6723 for (uint32_t parentIndex = startIndex; ;) {
6724 uint32_t childIndex = parentIndex * 2 + 1;
6725 if (childIndex >= heapSize) {
6726 break;
6727 }
6728
6729 if (childIndex + 1 < heapSize
6730 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6731 childIndex += 1;
6732 }
6733
6734 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6735 break;
6736 }
6737
6738 swap(heap[parentIndex], heap[childIndex]);
6739 parentIndex = childIndex;
6740 }
6741 }
6742
6743#if DEBUG_POINTER_ASSIGNMENT
6744 ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
6745 for (size_t i = 0; i < heapSize; i++) {
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006746 ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006747 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6748 heap[i].distance);
6749 }
6750#endif
6751
6752 // Pull matches out by increasing order of distance.
6753 // To avoid reassigning pointers that have already been matched, the loop keeps track
6754 // of which last and current pointers have been matched using the matchedXXXBits variables.
6755 // It also tracks the used pointer id bits.
6756 BitSet32 matchedLastBits(0);
6757 BitSet32 matchedCurrentBits(0);
6758 BitSet32 usedIdBits(0);
6759 bool first = true;
6760 for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
6761 while (heapSize > 0) {
6762 if (first) {
6763 // The first time through the loop, we just consume the root element of
6764 // the heap (the one with smallest distance).
6765 first = false;
6766 } else {
6767 // Previous iterations consumed the root element of the heap.
6768 // Pop root element off of the heap (sift down).
6769 heap[0] = heap[heapSize];
6770 for (uint32_t parentIndex = 0; ;) {
6771 uint32_t childIndex = parentIndex * 2 + 1;
6772 if (childIndex >= heapSize) {
6773 break;
6774 }
6775
6776 if (childIndex + 1 < heapSize
6777 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6778 childIndex += 1;
6779 }
6780
6781 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6782 break;
6783 }
6784
6785 swap(heap[parentIndex], heap[childIndex]);
6786 parentIndex = childIndex;
6787 }
6788
6789#if DEBUG_POINTER_ASSIGNMENT
6790 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
6791 for (size_t i = 0; i < heapSize; i++) {
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006792 ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006793 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6794 heap[i].distance);
6795 }
6796#endif
6797 }
6798
6799 heapSize -= 1;
6800
6801 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
6802 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
6803
6804 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
6805 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
6806
6807 matchedCurrentBits.markBit(currentPointerIndex);
6808 matchedLastBits.markBit(lastPointerIndex);
6809
Michael Wright842500e2015-03-13 17:32:02 -07006810 uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
6811 current->rawPointerData.pointers[currentPointerIndex].id = id;
6812 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6813 current->rawPointerData.markIdBit(id,
6814 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006815 usedIdBits.markBit(id);
6816
6817#if DEBUG_POINTER_ASSIGNMENT
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006818 ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
6819 ", id=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006820 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
6821#endif
6822 break;
6823 }
6824 }
6825
6826 // Assign fresh ids to pointers that were not matched in the process.
6827 for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
6828 uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
6829 uint32_t id = usedIdBits.markFirstUnmarkedBit();
6830
Michael Wright842500e2015-03-13 17:32:02 -07006831 current->rawPointerData.pointers[currentPointerIndex].id = id;
6832 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6833 current->rawPointerData.markIdBit(id,
6834 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006835
6836#if DEBUG_POINTER_ASSIGNMENT
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006837 ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006838#endif
6839 }
6840}
6841
6842int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
6843 if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
6844 return AKEY_STATE_VIRTUAL;
6845 }
6846
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006847 for (const VirtualKey& virtualKey : mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006848 if (virtualKey.keyCode == keyCode) {
6849 return AKEY_STATE_UP;
6850 }
6851 }
6852
6853 return AKEY_STATE_UNKNOWN;
6854}
6855
6856int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
6857 if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
6858 return AKEY_STATE_VIRTUAL;
6859 }
6860
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006861 for (const VirtualKey& virtualKey : mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006862 if (virtualKey.scanCode == scanCode) {
6863 return AKEY_STATE_UP;
6864 }
6865 }
6866
6867 return AKEY_STATE_UNKNOWN;
6868}
6869
6870bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
6871 const int32_t* keyCodes, uint8_t* outFlags) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006872 for (const VirtualKey& virtualKey : mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006873 for (size_t i = 0; i < numCodes; i++) {
6874 if (virtualKey.keyCode == keyCodes[i]) {
6875 outFlags[i] = 1;
6876 }
6877 }
6878 }
6879
6880 return true;
6881}
6882
Arthur Hung2c9a3342019-07-23 14:18:59 +08006883std::optional<int32_t> TouchInputMapper::getAssociatedDisplayId() {
Arthur Hungc23540e2018-11-29 20:42:11 +08006884 if (mParameters.hasAssociatedDisplay) {
6885 if (mDeviceMode == DEVICE_MODE_POINTER) {
6886 return std::make_optional(mPointerController->getDisplayId());
6887 } else {
6888 return std::make_optional(mViewport.displayId);
6889 }
6890 }
6891 return std::nullopt;
6892}
Michael Wrightd02c5b62014-02-10 15:10:22 -08006893
6894// --- SingleTouchInputMapper ---
6895
6896SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
6897 TouchInputMapper(device) {
6898}
6899
6900SingleTouchInputMapper::~SingleTouchInputMapper() {
6901}
6902
6903void SingleTouchInputMapper::reset(nsecs_t when) {
6904 mSingleTouchMotionAccumulator.reset(getDevice());
6905
6906 TouchInputMapper::reset(when);
6907}
6908
6909void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
6910 TouchInputMapper::process(rawEvent);
6911
6912 mSingleTouchMotionAccumulator.process(rawEvent);
6913}
6914
Michael Wright842500e2015-03-13 17:32:02 -07006915void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006916 if (mTouchButtonAccumulator.isToolActive()) {
Michael Wright842500e2015-03-13 17:32:02 -07006917 outState->rawPointerData.pointerCount = 1;
6918 outState->rawPointerData.idToIndex[0] = 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006919
6920 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6921 && (mTouchButtonAccumulator.isHovering()
6922 || (mRawPointerAxes.pressure.valid
6923 && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
Michael Wright842500e2015-03-13 17:32:02 -07006924 outState->rawPointerData.markIdBit(0, isHovering);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006925
Michael Wright842500e2015-03-13 17:32:02 -07006926 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006927 outPointer.id = 0;
6928 outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
6929 outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
6930 outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
6931 outPointer.touchMajor = 0;
6932 outPointer.touchMinor = 0;
6933 outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6934 outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6935 outPointer.orientation = 0;
6936 outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
6937 outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
6938 outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
6939 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6940 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6941 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6942 }
6943 outPointer.isHovering = isHovering;
6944 }
6945}
6946
6947void SingleTouchInputMapper::configureRawPointerAxes() {
6948 TouchInputMapper::configureRawPointerAxes();
6949
6950 getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
6951 getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
6952 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
6953 getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
6954 getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
6955 getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
6956 getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
6957}
6958
6959bool SingleTouchInputMapper::hasStylus() const {
6960 return mTouchButtonAccumulator.hasStylus();
6961}
6962
6963
6964// --- MultiTouchInputMapper ---
6965
6966MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
6967 TouchInputMapper(device) {
6968}
6969
6970MultiTouchInputMapper::~MultiTouchInputMapper() {
6971}
6972
6973void MultiTouchInputMapper::reset(nsecs_t when) {
6974 mMultiTouchMotionAccumulator.reset(getDevice());
6975
6976 mPointerIdBits.clear();
6977
6978 TouchInputMapper::reset(when);
6979}
6980
6981void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
6982 TouchInputMapper::process(rawEvent);
6983
6984 mMultiTouchMotionAccumulator.process(rawEvent);
6985}
6986
Michael Wright842500e2015-03-13 17:32:02 -07006987void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006988 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
6989 size_t outCount = 0;
6990 BitSet32 newPointerIdBits;
gaoshang1a632de2016-08-24 10:23:50 +08006991 mHavePointerIds = true;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006992
6993 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
6994 const MultiTouchMotionAccumulator::Slot* inSlot =
6995 mMultiTouchMotionAccumulator.getSlot(inIndex);
6996 if (!inSlot->isInUse()) {
6997 continue;
6998 }
6999
7000 if (outCount >= MAX_POINTERS) {
7001#if DEBUG_POINTERS
7002 ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
7003 "ignoring the rest.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007004 getDeviceName().c_str(), MAX_POINTERS);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007005#endif
7006 break; // too many fingers!
7007 }
7008
Michael Wright842500e2015-03-13 17:32:02 -07007009 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
Michael Wrightd02c5b62014-02-10 15:10:22 -08007010 outPointer.x = inSlot->getX();
7011 outPointer.y = inSlot->getY();
7012 outPointer.pressure = inSlot->getPressure();
7013 outPointer.touchMajor = inSlot->getTouchMajor();
7014 outPointer.touchMinor = inSlot->getTouchMinor();
7015 outPointer.toolMajor = inSlot->getToolMajor();
7016 outPointer.toolMinor = inSlot->getToolMinor();
7017 outPointer.orientation = inSlot->getOrientation();
7018 outPointer.distance = inSlot->getDistance();
7019 outPointer.tiltX = 0;
7020 outPointer.tiltY = 0;
7021
7022 outPointer.toolType = inSlot->getToolType();
7023 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
7024 outPointer.toolType = mTouchButtonAccumulator.getToolType();
7025 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
7026 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
7027 }
7028 }
7029
7030 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
7031 && (mTouchButtonAccumulator.isHovering()
7032 || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
7033 outPointer.isHovering = isHovering;
7034
7035 // Assign pointer id using tracking id if available.
gaoshang1a632de2016-08-24 10:23:50 +08007036 if (mHavePointerIds) {
7037 int32_t trackingId = inSlot->getTrackingId();
7038 int32_t id = -1;
7039 if (trackingId >= 0) {
7040 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
7041 uint32_t n = idBits.clearFirstMarkedBit();
7042 if (mPointerTrackingIdMap[n] == trackingId) {
7043 id = n;
7044 }
7045 }
7046
7047 if (id < 0 && !mPointerIdBits.isFull()) {
7048 id = mPointerIdBits.markFirstUnmarkedBit();
7049 mPointerTrackingIdMap[id] = trackingId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08007050 }
Michael Wright842500e2015-03-13 17:32:02 -07007051 }
gaoshang1a632de2016-08-24 10:23:50 +08007052 if (id < 0) {
7053 mHavePointerIds = false;
7054 outState->rawPointerData.clearIdBits();
7055 newPointerIdBits.clear();
7056 } else {
7057 outPointer.id = id;
7058 outState->rawPointerData.idToIndex[id] = outCount;
7059 outState->rawPointerData.markIdBit(id, isHovering);
7060 newPointerIdBits.markBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007061 }
Michael Wright842500e2015-03-13 17:32:02 -07007062 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08007063 outCount += 1;
7064 }
7065
Michael Wright842500e2015-03-13 17:32:02 -07007066 outState->rawPointerData.pointerCount = outCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08007067 mPointerIdBits = newPointerIdBits;
7068
7069 mMultiTouchMotionAccumulator.finishSync();
7070}
7071
7072void MultiTouchInputMapper::configureRawPointerAxes() {
7073 TouchInputMapper::configureRawPointerAxes();
7074
7075 getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
7076 getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
7077 getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
7078 getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
7079 getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
7080 getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
7081 getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
7082 getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
7083 getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
7084 getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
7085 getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
7086
7087 if (mRawPointerAxes.trackingId.valid
7088 && mRawPointerAxes.slot.valid
7089 && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
7090 size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
7091 if (slotCount > MAX_SLOTS) {
Narayan Kamath37764c72014-03-27 14:21:09 +00007092 ALOGW("MultiTouch Device %s reported %zu slots but the framework "
7093 "only supports a maximum of %zu slots at this time.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007094 getDeviceName().c_str(), slotCount, MAX_SLOTS);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007095 slotCount = MAX_SLOTS;
7096 }
7097 mMultiTouchMotionAccumulator.configure(getDevice(),
7098 slotCount, true /*usingSlotsProtocol*/);
7099 } else {
7100 mMultiTouchMotionAccumulator.configure(getDevice(),
7101 MAX_POINTERS, false /*usingSlotsProtocol*/);
7102 }
7103}
7104
7105bool MultiTouchInputMapper::hasStylus() const {
7106 return mMultiTouchMotionAccumulator.hasStylus()
7107 || mTouchButtonAccumulator.hasStylus();
7108}
7109
Michael Wright842500e2015-03-13 17:32:02 -07007110// --- ExternalStylusInputMapper
7111
7112ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
7113 InputMapper(device) {
7114
7115}
7116
7117uint32_t ExternalStylusInputMapper::getSources() {
7118 return AINPUT_SOURCE_STYLUS;
7119}
7120
7121void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
7122 InputMapper::populateDeviceInfo(info);
7123 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
7124 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
7125}
7126
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007127void ExternalStylusInputMapper::dump(std::string& dump) {
7128 dump += INDENT2 "External Stylus Input Mapper:\n";
7129 dump += INDENT3 "Raw Stylus Axes:\n";
Michael Wright842500e2015-03-13 17:32:02 -07007130 dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007131 dump += INDENT3 "Stylus State:\n";
Michael Wright842500e2015-03-13 17:32:02 -07007132 dumpStylusState(dump, mStylusState);
7133}
7134
7135void ExternalStylusInputMapper::configure(nsecs_t when,
7136 const InputReaderConfiguration* config, uint32_t changes) {
7137 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
7138 mTouchButtonAccumulator.configure(getDevice());
7139}
7140
7141void ExternalStylusInputMapper::reset(nsecs_t when) {
7142 InputDevice* device = getDevice();
7143 mSingleTouchMotionAccumulator.reset(device);
7144 mTouchButtonAccumulator.reset(device);
7145 InputMapper::reset(when);
7146}
7147
7148void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
7149 mSingleTouchMotionAccumulator.process(rawEvent);
7150 mTouchButtonAccumulator.process(rawEvent);
7151
7152 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
7153 sync(rawEvent->when);
7154 }
7155}
7156
7157void ExternalStylusInputMapper::sync(nsecs_t when) {
7158 mStylusState.clear();
7159
7160 mStylusState.when = when;
7161
Michael Wright45ccacf2015-04-21 19:01:58 +01007162 mStylusState.toolType = mTouchButtonAccumulator.getToolType();
7163 if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
7164 mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
7165 }
7166
Michael Wright842500e2015-03-13 17:32:02 -07007167 int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
7168 if (mRawPressureAxis.valid) {
7169 mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
7170 } else if (mTouchButtonAccumulator.isToolActive()) {
7171 mStylusState.pressure = 1.0f;
7172 } else {
7173 mStylusState.pressure = 0.0f;
7174 }
7175
7176 mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
Michael Wright842500e2015-03-13 17:32:02 -07007177
7178 mContext->dispatchExternalStylusState(mStylusState);
7179}
7180
Michael Wrightd02c5b62014-02-10 15:10:22 -08007181
7182// --- JoystickInputMapper ---
7183
7184JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
7185 InputMapper(device) {
7186}
7187
7188JoystickInputMapper::~JoystickInputMapper() {
7189}
7190
7191uint32_t JoystickInputMapper::getSources() {
7192 return AINPUT_SOURCE_JOYSTICK;
7193}
7194
7195void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
7196 InputMapper::populateDeviceInfo(info);
7197
7198 for (size_t i = 0; i < mAxes.size(); i++) {
7199 const Axis& axis = mAxes.valueAt(i);
7200 addMotionRange(axis.axisInfo.axis, axis, info);
7201
7202 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7203 addMotionRange(axis.axisInfo.highAxis, axis, info);
7204
7205 }
7206 }
7207}
7208
7209void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
7210 InputDeviceInfo* info) {
7211 info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
7212 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
7213 /* In order to ease the transition for developers from using the old axes
7214 * to the newer, more semantically correct axes, we'll continue to register
7215 * the old axes as duplicates of their corresponding new ones. */
7216 int32_t compatAxis = getCompatAxis(axisId);
7217 if (compatAxis >= 0) {
7218 info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
7219 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
7220 }
7221}
7222
7223/* A mapping from axes the joystick actually has to the axes that should be
7224 * artificially created for compatibility purposes.
7225 * Returns -1 if no compatibility axis is needed. */
7226int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
7227 switch(axis) {
7228 case AMOTION_EVENT_AXIS_LTRIGGER:
7229 return AMOTION_EVENT_AXIS_BRAKE;
7230 case AMOTION_EVENT_AXIS_RTRIGGER:
7231 return AMOTION_EVENT_AXIS_GAS;
7232 }
7233 return -1;
7234}
7235
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007236void JoystickInputMapper::dump(std::string& dump) {
7237 dump += INDENT2 "Joystick Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007238
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007239 dump += INDENT3 "Axes:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007240 size_t numAxes = mAxes.size();
7241 for (size_t i = 0; i < numAxes; i++) {
7242 const Axis& axis = mAxes.valueAt(i);
7243 const char* label = getAxisLabel(axis.axisInfo.axis);
7244 if (label) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007245 dump += StringPrintf(INDENT4 "%s", label);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007246 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007247 dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007248 }
7249 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7250 label = getAxisLabel(axis.axisInfo.highAxis);
7251 if (label) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007252 dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007253 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007254 dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
Michael Wrightd02c5b62014-02-10 15:10:22 -08007255 axis.axisInfo.splitValue);
7256 }
7257 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007258 dump += " (invert)";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007259 }
7260
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007261 dump += StringPrintf(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08007262 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007263 dump += StringPrintf(INDENT4 " scale=%0.5f, offset=%0.5f, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08007264 "highScale=%0.5f, highOffset=%0.5f\n",
7265 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007266 dump += StringPrintf(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08007267 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
7268 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
7269 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
7270 }
7271}
7272
7273void JoystickInputMapper::configure(nsecs_t when,
7274 const InputReaderConfiguration* config, uint32_t changes) {
7275 InputMapper::configure(when, config, changes);
7276
7277 if (!changes) { // first time only
7278 // Collect all axes.
7279 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
7280 if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
7281 & INPUT_DEVICE_CLASS_JOYSTICK)) {
7282 continue; // axis must be claimed by a different device
7283 }
7284
7285 RawAbsoluteAxisInfo rawAxisInfo;
7286 getAbsoluteAxisInfo(abs, &rawAxisInfo);
7287 if (rawAxisInfo.valid) {
7288 // Map axis.
7289 AxisInfo axisInfo;
7290 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
7291 if (!explicitlyMapped) {
7292 // Axis is not explicitly mapped, will choose a generic axis later.
7293 axisInfo.mode = AxisInfo::MODE_NORMAL;
7294 axisInfo.axis = -1;
7295 }
7296
7297 // Apply flat override.
7298 int32_t rawFlat = axisInfo.flatOverride < 0
7299 ? rawAxisInfo.flat : axisInfo.flatOverride;
7300
7301 // Calculate scaling factors and limits.
7302 Axis axis;
7303 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
7304 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
7305 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
7306 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7307 scale, 0.0f, highScale, 0.0f,
7308 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7309 rawAxisInfo.resolution * scale);
7310 } else if (isCenteredAxis(axisInfo.axis)) {
7311 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
7312 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
7313 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7314 scale, offset, scale, offset,
7315 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7316 rawAxisInfo.resolution * scale);
7317 } else {
7318 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
7319 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7320 scale, 0.0f, scale, 0.0f,
7321 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7322 rawAxisInfo.resolution * scale);
7323 }
7324
7325 // To eliminate noise while the joystick is at rest, filter out small variations
7326 // in axis values up front.
7327 axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
7328
7329 mAxes.add(abs, axis);
7330 }
7331 }
7332
7333 // If there are too many axes, start dropping them.
7334 // Prefer to keep explicitly mapped axes.
7335 if (mAxes.size() > PointerCoords::MAX_AXES) {
Narayan Kamath37764c72014-03-27 14:21:09 +00007336 ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007337 getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007338 pruneAxes(true);
7339 pruneAxes(false);
7340 }
7341
7342 // Assign generic axis ids to remaining axes.
7343 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
7344 size_t numAxes = mAxes.size();
7345 for (size_t i = 0; i < numAxes; i++) {
7346 Axis& axis = mAxes.editValueAt(i);
7347 if (axis.axisInfo.axis < 0) {
7348 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
7349 && haveAxis(nextGenericAxisId)) {
7350 nextGenericAxisId += 1;
7351 }
7352
7353 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
7354 axis.axisInfo.axis = nextGenericAxisId;
7355 nextGenericAxisId += 1;
7356 } else {
7357 ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
7358 "have already been assigned to other axes.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007359 getDeviceName().c_str(), mAxes.keyAt(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08007360 mAxes.removeItemsAt(i--);
7361 numAxes -= 1;
7362 }
7363 }
7364 }
7365 }
7366}
7367
7368bool JoystickInputMapper::haveAxis(int32_t axisId) {
7369 size_t numAxes = mAxes.size();
7370 for (size_t i = 0; i < numAxes; i++) {
7371 const Axis& axis = mAxes.valueAt(i);
7372 if (axis.axisInfo.axis == axisId
7373 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
7374 && axis.axisInfo.highAxis == axisId)) {
7375 return true;
7376 }
7377 }
7378 return false;
7379}
7380
7381void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
7382 size_t i = mAxes.size();
7383 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
7384 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
7385 continue;
7386 }
7387 ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007388 getDeviceName().c_str(), mAxes.keyAt(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08007389 mAxes.removeItemsAt(i);
7390 }
7391}
7392
7393bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
7394 switch (axis) {
7395 case AMOTION_EVENT_AXIS_X:
7396 case AMOTION_EVENT_AXIS_Y:
7397 case AMOTION_EVENT_AXIS_Z:
7398 case AMOTION_EVENT_AXIS_RX:
7399 case AMOTION_EVENT_AXIS_RY:
7400 case AMOTION_EVENT_AXIS_RZ:
7401 case AMOTION_EVENT_AXIS_HAT_X:
7402 case AMOTION_EVENT_AXIS_HAT_Y:
7403 case AMOTION_EVENT_AXIS_ORIENTATION:
7404 case AMOTION_EVENT_AXIS_RUDDER:
7405 case AMOTION_EVENT_AXIS_WHEEL:
7406 return true;
7407 default:
7408 return false;
7409 }
7410}
7411
7412void JoystickInputMapper::reset(nsecs_t when) {
7413 // Recenter all axes.
7414 size_t numAxes = mAxes.size();
7415 for (size_t i = 0; i < numAxes; i++) {
7416 Axis& axis = mAxes.editValueAt(i);
7417 axis.resetValue();
7418 }
7419
7420 InputMapper::reset(when);
7421}
7422
7423void JoystickInputMapper::process(const RawEvent* rawEvent) {
7424 switch (rawEvent->type) {
7425 case EV_ABS: {
7426 ssize_t index = mAxes.indexOfKey(rawEvent->code);
7427 if (index >= 0) {
7428 Axis& axis = mAxes.editValueAt(index);
7429 float newValue, highNewValue;
7430 switch (axis.axisInfo.mode) {
7431 case AxisInfo::MODE_INVERT:
7432 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
7433 * axis.scale + axis.offset;
7434 highNewValue = 0.0f;
7435 break;
7436 case AxisInfo::MODE_SPLIT:
7437 if (rawEvent->value < axis.axisInfo.splitValue) {
7438 newValue = (axis.axisInfo.splitValue - rawEvent->value)
7439 * axis.scale + axis.offset;
7440 highNewValue = 0.0f;
7441 } else if (rawEvent->value > axis.axisInfo.splitValue) {
7442 newValue = 0.0f;
7443 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
7444 * axis.highScale + axis.highOffset;
7445 } else {
7446 newValue = 0.0f;
7447 highNewValue = 0.0f;
7448 }
7449 break;
7450 default:
7451 newValue = rawEvent->value * axis.scale + axis.offset;
7452 highNewValue = 0.0f;
7453 break;
7454 }
7455 axis.newValue = newValue;
7456 axis.highNewValue = highNewValue;
7457 }
7458 break;
7459 }
7460
7461 case EV_SYN:
7462 switch (rawEvent->code) {
7463 case SYN_REPORT:
7464 sync(rawEvent->when, false /*force*/);
7465 break;
7466 }
7467 break;
7468 }
7469}
7470
7471void JoystickInputMapper::sync(nsecs_t when, bool force) {
7472 if (!filterAxes(force)) {
7473 return;
7474 }
7475
7476 int32_t metaState = mContext->getGlobalMetaState();
7477 int32_t buttonState = 0;
7478
7479 PointerProperties pointerProperties;
7480 pointerProperties.clear();
7481 pointerProperties.id = 0;
7482 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
7483
7484 PointerCoords pointerCoords;
7485 pointerCoords.clear();
7486
7487 size_t numAxes = mAxes.size();
7488 for (size_t i = 0; i < numAxes; i++) {
7489 const Axis& axis = mAxes.valueAt(i);
7490 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
7491 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7492 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
7493 axis.highCurrentValue);
7494 }
7495 }
7496
7497 // Moving a joystick axis should not wake the device because joysticks can
7498 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
7499 // button will likely wake the device.
7500 // TODO: Use the input device configuration to control this behavior more finely.
7501 uint32_t policyFlags = 0;
7502
Prabir Pradhan42611e02018-11-27 14:04:02 -08007503 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07007504 AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
7505 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07007506 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
7507 &pointerProperties, &pointerCoords, 0, 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07007508 AMOTION_EVENT_INVALID_CURSOR_POSITION,
7509 AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08007510 getListener()->notifyMotion(&args);
7511}
7512
7513void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
7514 int32_t axis, float value) {
7515 pointerCoords->setAxisValue(axis, value);
7516 /* In order to ease the transition for developers from using the old axes
7517 * to the newer, more semantically correct axes, we'll continue to produce
7518 * values for the old axes as mirrors of the value of their corresponding
7519 * new axes. */
7520 int32_t compatAxis = getCompatAxis(axis);
7521 if (compatAxis >= 0) {
7522 pointerCoords->setAxisValue(compatAxis, value);
7523 }
7524}
7525
7526bool JoystickInputMapper::filterAxes(bool force) {
7527 bool atLeastOneSignificantChange = force;
7528 size_t numAxes = mAxes.size();
7529 for (size_t i = 0; i < numAxes; i++) {
7530 Axis& axis = mAxes.editValueAt(i);
7531 if (force || hasValueChangedSignificantly(axis.filter,
7532 axis.newValue, axis.currentValue, axis.min, axis.max)) {
7533 axis.currentValue = axis.newValue;
7534 atLeastOneSignificantChange = true;
7535 }
7536 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7537 if (force || hasValueChangedSignificantly(axis.filter,
7538 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
7539 axis.highCurrentValue = axis.highNewValue;
7540 atLeastOneSignificantChange = true;
7541 }
7542 }
7543 }
7544 return atLeastOneSignificantChange;
7545}
7546
7547bool JoystickInputMapper::hasValueChangedSignificantly(
7548 float filter, float newValue, float currentValue, float min, float max) {
7549 if (newValue != currentValue) {
7550 // Filter out small changes in value unless the value is converging on the axis
7551 // bounds or center point. This is intended to reduce the amount of information
7552 // sent to applications by particularly noisy joysticks (such as PS3).
7553 if (fabs(newValue - currentValue) > filter
7554 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
7555 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
7556 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
7557 return true;
7558 }
7559 }
7560 return false;
7561}
7562
7563bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
7564 float filter, float newValue, float currentValue, float thresholdValue) {
7565 float newDistance = fabs(newValue - thresholdValue);
7566 if (newDistance < filter) {
7567 float oldDistance = fabs(currentValue - thresholdValue);
7568 if (newDistance < oldDistance) {
7569 return true;
7570 }
7571 }
7572 return false;
7573}
7574
7575} // namespace android