blob: d565e3ab384f76410ffebe4990016375a8840952 [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
259InputReader::InputReader(const sp<EventHubInterface>& eventHub,
260 const sp<InputReaderPolicyInterface>& policy,
261 const sp<InputListenerInterface>& listener) :
262 mContext(this), mEventHub(eventHub), mPolicy(policy),
Prabir Pradhan42611e02018-11-27 14:04:02 -0800263 mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800264 mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
265 mConfigurationChangesToRefresh(0) {
266 mQueuedListener = new QueuedInputListener(listener);
267
268 { // acquire lock
269 AutoMutex _l(mLock);
270
271 refreshConfigurationLocked(0);
272 updateGlobalMetaStateLocked();
273 } // release lock
274}
275
276InputReader::~InputReader() {
277 for (size_t i = 0; i < mDevices.size(); i++) {
278 delete mDevices.valueAt(i);
279 }
280}
281
282void InputReader::loopOnce() {
283 int32_t oldGeneration;
284 int32_t timeoutMillis;
285 bool inputDevicesChanged = false;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800286 std::vector<InputDeviceInfo> inputDevices;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800287 { // acquire lock
288 AutoMutex _l(mLock);
289
290 oldGeneration = mGeneration;
291 timeoutMillis = -1;
292
293 uint32_t changes = mConfigurationChangesToRefresh;
294 if (changes) {
295 mConfigurationChangesToRefresh = 0;
296 timeoutMillis = 0;
297 refreshConfigurationLocked(changes);
298 } else if (mNextTimeout != LLONG_MAX) {
299 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
300 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
301 }
302 } // release lock
303
304 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
305
306 { // acquire lock
307 AutoMutex _l(mLock);
308 mReaderIsAliveCondition.broadcast();
309
310 if (count) {
311 processEventsLocked(mEventBuffer, count);
312 }
313
314 if (mNextTimeout != LLONG_MAX) {
315 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
316 if (now >= mNextTimeout) {
317#if DEBUG_RAW_EVENTS
318 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
319#endif
320 mNextTimeout = LLONG_MAX;
321 timeoutExpiredLocked(now);
322 }
323 }
324
325 if (oldGeneration != mGeneration) {
326 inputDevicesChanged = true;
327 getInputDevicesLocked(inputDevices);
328 }
329 } // release lock
330
331 // Send out a message that the describes the changed input devices.
332 if (inputDevicesChanged) {
333 mPolicy->notifyInputDevicesChanged(inputDevices);
334 }
335
336 // Flush queued events out to the listener.
337 // This must happen outside of the lock because the listener could potentially call
338 // back into the InputReader's methods, such as getScanCodeState, or become blocked
339 // on another thread similarly waiting to acquire the InputReader lock thereby
340 // resulting in a deadlock. This situation is actually quite plausible because the
341 // listener is actually the input dispatcher, which calls into the window manager,
342 // which occasionally calls into the input reader.
343 mQueuedListener->flush();
344}
345
346void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
347 for (const RawEvent* rawEvent = rawEvents; count;) {
348 int32_t type = rawEvent->type;
349 size_t batchSize = 1;
350 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
351 int32_t deviceId = rawEvent->deviceId;
352 while (batchSize < count) {
353 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
354 || rawEvent[batchSize].deviceId != deviceId) {
355 break;
356 }
357 batchSize += 1;
358 }
359#if DEBUG_RAW_EVENTS
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -0700360 ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361#endif
362 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
363 } else {
364 switch (rawEvent->type) {
365 case EventHubInterface::DEVICE_ADDED:
366 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
367 break;
368 case EventHubInterface::DEVICE_REMOVED:
369 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
370 break;
371 case EventHubInterface::FINISHED_DEVICE_SCAN:
372 handleConfigurationChangedLocked(rawEvent->when);
373 break;
374 default:
375 ALOG_ASSERT(false); // can't happen
376 break;
377 }
378 }
379 count -= batchSize;
380 rawEvent += batchSize;
381 }
382}
383
384void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
385 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
386 if (deviceIndex >= 0) {
387 ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
388 return;
389 }
390
391 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
392 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
393 int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
394
395 InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
396 device->configure(when, &mConfig, 0);
397 device->reset(when);
398
399 if (device->isIgnored()) {
400 ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100401 identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800402 } else {
403 ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100404 identifier.name.c_str(), device->getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800405 }
406
407 mDevices.add(deviceId, device);
408 bumpGenerationLocked();
Michael Wright842500e2015-03-13 17:32:02 -0700409
410 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
411 notifyExternalStylusPresenceChanged();
412 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800413}
414
415void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
Yi Kong9b14ac62018-07-17 13:48:38 -0700416 InputDevice* device = nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800417 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
418 if (deviceIndex < 0) {
419 ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
420 return;
421 }
422
423 device = mDevices.valueAt(deviceIndex);
424 mDevices.removeItemsAt(deviceIndex, 1);
425 bumpGenerationLocked();
426
427 if (device->isIgnored()) {
428 ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100429 device->getId(), device->getName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800430 } else {
431 ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100432 device->getId(), device->getName().c_str(), device->getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800433 }
434
Michael Wright842500e2015-03-13 17:32:02 -0700435 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
436 notifyExternalStylusPresenceChanged();
437 }
438
Michael Wrightd02c5b62014-02-10 15:10:22 -0800439 device->reset(when);
440 delete device;
441}
442
443InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
444 const InputDeviceIdentifier& identifier, uint32_t classes) {
445 InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
446 controllerNumber, identifier, classes);
447
448 // External devices.
449 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
450 device->setExternal(true);
451 }
452
Tim Kilbourn063ff532015-04-08 10:26:18 -0700453 // Devices with mics.
454 if (classes & INPUT_DEVICE_CLASS_MIC) {
455 device->setMic(true);
456 }
457
Michael Wrightd02c5b62014-02-10 15:10:22 -0800458 // Switch-like devices.
459 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
460 device->addMapper(new SwitchInputMapper(device));
461 }
462
Prashant Malani1941ff52015-08-11 18:29:28 -0700463 // Scroll wheel-like devices.
464 if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
465 device->addMapper(new RotaryEncoderInputMapper(device));
466 }
467
Michael Wrightd02c5b62014-02-10 15:10:22 -0800468 // Vibrator-like devices.
469 if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
470 device->addMapper(new VibratorInputMapper(device));
471 }
472
473 // Keyboard-like devices.
474 uint32_t keyboardSource = 0;
475 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
476 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
477 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
478 }
479 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
480 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
481 }
482 if (classes & INPUT_DEVICE_CLASS_DPAD) {
483 keyboardSource |= AINPUT_SOURCE_DPAD;
484 }
485 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
486 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
487 }
488
489 if (keyboardSource != 0) {
490 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
491 }
492
493 // Cursor-like devices.
494 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
495 device->addMapper(new CursorInputMapper(device));
496 }
497
498 // Touchscreens and touchpad devices.
499 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
500 device->addMapper(new MultiTouchInputMapper(device));
501 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
502 device->addMapper(new SingleTouchInputMapper(device));
503 }
504
505 // Joystick-like devices.
506 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
507 device->addMapper(new JoystickInputMapper(device));
508 }
509
Michael Wright842500e2015-03-13 17:32:02 -0700510 // External stylus-like devices.
511 if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
512 device->addMapper(new ExternalStylusInputMapper(device));
513 }
514
Michael Wrightd02c5b62014-02-10 15:10:22 -0800515 return device;
516}
517
518void InputReader::processEventsForDeviceLocked(int32_t deviceId,
519 const RawEvent* rawEvents, size_t count) {
520 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
521 if (deviceIndex < 0) {
522 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
523 return;
524 }
525
526 InputDevice* device = mDevices.valueAt(deviceIndex);
527 if (device->isIgnored()) {
528 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
529 return;
530 }
531
532 device->process(rawEvents, count);
533}
534
535void InputReader::timeoutExpiredLocked(nsecs_t when) {
536 for (size_t i = 0; i < mDevices.size(); i++) {
537 InputDevice* device = mDevices.valueAt(i);
538 if (!device->isIgnored()) {
539 device->timeoutExpired(when);
540 }
541 }
542}
543
544void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
545 // Reset global meta state because it depends on the list of all configured devices.
546 updateGlobalMetaStateLocked();
547
548 // Enqueue configuration changed.
Prabir Pradhan42611e02018-11-27 14:04:02 -0800549 NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800550 mQueuedListener->notifyConfigurationChanged(&args);
551}
552
553void InputReader::refreshConfigurationLocked(uint32_t changes) {
554 mPolicy->getReaderConfiguration(&mConfig);
555 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
556
557 if (changes) {
Siarhei Vishniakouc5ae0dc2019-07-10 15:51:18 -0700558 ALOGI("Reconfiguring input devices, changes=%s",
559 InputReaderConfiguration::changesToString(changes).c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800560 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
561
562 if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
563 mEventHub->requestReopenDevices();
564 } else {
565 for (size_t i = 0; i < mDevices.size(); i++) {
566 InputDevice* device = mDevices.valueAt(i);
567 device->configure(now, &mConfig, changes);
568 }
569 }
570 }
571}
572
573void InputReader::updateGlobalMetaStateLocked() {
574 mGlobalMetaState = 0;
575
576 for (size_t i = 0; i < mDevices.size(); i++) {
577 InputDevice* device = mDevices.valueAt(i);
578 mGlobalMetaState |= device->getMetaState();
579 }
580}
581
582int32_t InputReader::getGlobalMetaStateLocked() {
583 return mGlobalMetaState;
584}
585
Michael Wright842500e2015-03-13 17:32:02 -0700586void InputReader::notifyExternalStylusPresenceChanged() {
587 refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
588}
589
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800590void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
Michael Wright842500e2015-03-13 17:32:02 -0700591 for (size_t i = 0; i < mDevices.size(); i++) {
592 InputDevice* device = mDevices.valueAt(i);
593 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800594 InputDeviceInfo info;
595 device->getDeviceInfo(&info);
596 outDevices.push_back(info);
Michael Wright842500e2015-03-13 17:32:02 -0700597 }
598 }
599}
600
601void InputReader::dispatchExternalStylusState(const StylusState& state) {
602 for (size_t i = 0; i < mDevices.size(); i++) {
603 InputDevice* device = mDevices.valueAt(i);
604 device->updateExternalStylusState(state);
605 }
606}
607
Michael Wrightd02c5b62014-02-10 15:10:22 -0800608void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
609 mDisableVirtualKeysTimeout = time;
610}
611
612bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
613 InputDevice* device, int32_t keyCode, int32_t scanCode) {
614 if (now < mDisableVirtualKeysTimeout) {
615 ALOGI("Dropping virtual key from device %s because virtual keys are "
616 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100617 device->getName().c_str(),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800618 (mDisableVirtualKeysTimeout - now) * 0.000001,
619 keyCode, scanCode);
620 return true;
621 } else {
622 return false;
623 }
624}
625
626void InputReader::fadePointerLocked() {
627 for (size_t i = 0; i < mDevices.size(); i++) {
628 InputDevice* device = mDevices.valueAt(i);
629 device->fadePointer();
630 }
631}
632
633void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
634 if (when < mNextTimeout) {
635 mNextTimeout = when;
636 mEventHub->wake();
637 }
638}
639
640int32_t InputReader::bumpGenerationLocked() {
641 return ++mGeneration;
642}
643
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800644void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800645 AutoMutex _l(mLock);
646 getInputDevicesLocked(outInputDevices);
647}
648
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800649void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800650 outInputDevices.clear();
651
652 size_t numDevices = mDevices.size();
653 for (size_t i = 0; i < numDevices; i++) {
654 InputDevice* device = mDevices.valueAt(i);
655 if (!device->isIgnored()) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800656 InputDeviceInfo info;
657 device->getDeviceInfo(&info);
658 outInputDevices.push_back(info);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659 }
660 }
661}
662
663int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
664 int32_t keyCode) {
665 AutoMutex _l(mLock);
666
667 return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
668}
669
670int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
671 int32_t scanCode) {
672 AutoMutex _l(mLock);
673
674 return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
675}
676
677int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
678 AutoMutex _l(mLock);
679
680 return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
681}
682
683int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
684 GetStateFunc getStateFunc) {
685 int32_t result = AKEY_STATE_UNKNOWN;
686 if (deviceId >= 0) {
687 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
688 if (deviceIndex >= 0) {
689 InputDevice* device = mDevices.valueAt(deviceIndex);
690 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
691 result = (device->*getStateFunc)(sourceMask, code);
692 }
693 }
694 } else {
695 size_t numDevices = mDevices.size();
696 for (size_t i = 0; i < numDevices; i++) {
697 InputDevice* device = mDevices.valueAt(i);
698 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
699 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
700 // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
701 int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
702 if (currentResult >= AKEY_STATE_DOWN) {
703 return currentResult;
704 } else if (currentResult == AKEY_STATE_UP) {
705 result = currentResult;
706 }
707 }
708 }
709 }
710 return result;
711}
712
Andrii Kulian763a3a42016-03-08 10:46:16 -0800713void InputReader::toggleCapsLockState(int32_t deviceId) {
714 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
715 if (deviceIndex < 0) {
716 ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
717 return;
718 }
719
720 InputDevice* device = mDevices.valueAt(deviceIndex);
721 if (device->isIgnored()) {
722 return;
723 }
724
725 device->updateMetaState(AKEYCODE_CAPS_LOCK);
726}
727
Michael Wrightd02c5b62014-02-10 15:10:22 -0800728bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
729 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
730 AutoMutex _l(mLock);
731
732 memset(outFlags, 0, numCodes);
733 return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
734}
735
736bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
737 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
738 bool result = false;
739 if (deviceId >= 0) {
740 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
741 if (deviceIndex >= 0) {
742 InputDevice* device = mDevices.valueAt(deviceIndex);
743 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
744 result = device->markSupportedKeyCodes(sourceMask,
745 numCodes, keyCodes, outFlags);
746 }
747 }
748 } else {
749 size_t numDevices = mDevices.size();
750 for (size_t i = 0; i < numDevices; i++) {
751 InputDevice* device = mDevices.valueAt(i);
752 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
753 result |= device->markSupportedKeyCodes(sourceMask,
754 numCodes, keyCodes, outFlags);
755 }
756 }
757 }
758 return result;
759}
760
761void InputReader::requestRefreshConfiguration(uint32_t changes) {
762 AutoMutex _l(mLock);
763
764 if (changes) {
765 bool needWake = !mConfigurationChangesToRefresh;
766 mConfigurationChangesToRefresh |= changes;
767
768 if (needWake) {
769 mEventHub->wake();
770 }
771 }
772}
773
774void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
775 ssize_t repeat, int32_t token) {
776 AutoMutex _l(mLock);
777
778 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
779 if (deviceIndex >= 0) {
780 InputDevice* device = mDevices.valueAt(deviceIndex);
781 device->vibrate(pattern, patternSize, repeat, token);
782 }
783}
784
785void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
786 AutoMutex _l(mLock);
787
788 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
789 if (deviceIndex >= 0) {
790 InputDevice* device = mDevices.valueAt(deviceIndex);
791 device->cancelVibrate(token);
792 }
793}
794
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700795bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
796 AutoMutex _l(mLock);
797
798 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
799 if (deviceIndex >= 0) {
800 InputDevice* device = mDevices.valueAt(deviceIndex);
801 return device->isEnabled();
802 }
803 ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
804 return false;
805}
806
Arthur Hungc23540e2018-11-29 20:42:11 +0800807bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
808 AutoMutex _l(mLock);
809
810 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
811 if (deviceIndex < 0) {
812 ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
813 return false;
814 }
815
816 InputDevice* device = mDevices.valueAt(deviceIndex);
817 std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
818 // No associated display. By default, can dispatch to all displays.
819 if (!associatedDisplayId) {
820 return true;
821 }
822
823 if (*associatedDisplayId == ADISPLAY_ID_NONE) {
824 ALOGW("Device has associated, but no associated display id.");
825 return true;
826 }
827
828 return *associatedDisplayId == displayId;
829}
830
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800831void InputReader::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800832 AutoMutex _l(mLock);
833
834 mEventHub->dump(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800835 dump += "\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800836
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800837 dump += "Input Reader State:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800838
839 for (size_t i = 0; i < mDevices.size(); i++) {
840 mDevices.valueAt(i)->dump(dump);
841 }
842
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800843 dump += INDENT "Configuration:\n";
844 dump += INDENT2 "ExcludedDeviceNames: [";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800845 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
846 if (i != 0) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800847 dump += ", ";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800848 }
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100849 dump += mConfig.excludedDeviceNames[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -0800850 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800851 dump += "]\n";
852 dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800853 mConfig.virtualKeyQuietTime * 0.000001f);
854
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800855 dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
Michael Wrightd02c5b62014-02-10 15:10:22 -0800856 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
857 mConfig.pointerVelocityControlParameters.scale,
858 mConfig.pointerVelocityControlParameters.lowThreshold,
859 mConfig.pointerVelocityControlParameters.highThreshold,
860 mConfig.pointerVelocityControlParameters.acceleration);
861
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800862 dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
Michael Wrightd02c5b62014-02-10 15:10:22 -0800863 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
864 mConfig.wheelVelocityControlParameters.scale,
865 mConfig.wheelVelocityControlParameters.lowThreshold,
866 mConfig.wheelVelocityControlParameters.highThreshold,
867 mConfig.wheelVelocityControlParameters.acceleration);
868
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800869 dump += StringPrintf(INDENT2 "PointerGesture:\n");
870 dump += StringPrintf(INDENT3 "Enabled: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800871 toString(mConfig.pointerGesturesEnabled));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800872 dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800873 mConfig.pointerGestureQuietInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800874 dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800875 mConfig.pointerGestureDragMinSwitchSpeed);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800876 dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800877 mConfig.pointerGestureTapInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800878 dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800879 mConfig.pointerGestureTapDragInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800880 dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800881 mConfig.pointerGestureTapSlop);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800882 dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800883 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800884 dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800885 mConfig.pointerGestureMultitouchMinDistance);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800886 dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800887 mConfig.pointerGestureSwipeTransitionAngleCosine);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800888 dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800889 mConfig.pointerGestureSwipeMaxWidthRatio);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800890 dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800891 mConfig.pointerGestureMovementSpeedRatio);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800892 dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800893 mConfig.pointerGestureZoomSpeedRatio);
Santos Cordonfa5cf462017-04-05 10:37:00 -0700894
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800895 dump += INDENT3 "Viewports:\n";
Santos Cordonfa5cf462017-04-05 10:37:00 -0700896 mConfig.dump(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800897}
898
899void InputReader::monitor() {
900 // Acquire and release the lock to ensure that the reader has not deadlocked.
901 mLock.lock();
902 mEventHub->wake();
903 mReaderIsAliveCondition.wait(mLock);
904 mLock.unlock();
905
906 // Check the EventHub
907 mEventHub->monitor();
908}
909
910
911// --- InputReader::ContextImpl ---
912
913InputReader::ContextImpl::ContextImpl(InputReader* reader) :
914 mReader(reader) {
915}
916
917void InputReader::ContextImpl::updateGlobalMetaState() {
918 // lock is already held by the input loop
919 mReader->updateGlobalMetaStateLocked();
920}
921
922int32_t InputReader::ContextImpl::getGlobalMetaState() {
923 // lock is already held by the input loop
924 return mReader->getGlobalMetaStateLocked();
925}
926
927void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
928 // lock is already held by the input loop
929 mReader->disableVirtualKeysUntilLocked(time);
930}
931
932bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
933 InputDevice* device, int32_t keyCode, int32_t scanCode) {
934 // lock is already held by the input loop
935 return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
936}
937
938void InputReader::ContextImpl::fadePointer() {
939 // lock is already held by the input loop
940 mReader->fadePointerLocked();
941}
942
943void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
944 // lock is already held by the input loop
945 mReader->requestTimeoutAtTimeLocked(when);
946}
947
948int32_t InputReader::ContextImpl::bumpGeneration() {
949 // lock is already held by the input loop
950 return mReader->bumpGenerationLocked();
951}
952
Arthur Hung7c3ae9c2019-03-11 11:23:03 +0800953void InputReader::ContextImpl::getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
Michael Wright842500e2015-03-13 17:32:02 -0700954 // lock is already held by whatever called refreshConfigurationLocked
955 mReader->getExternalStylusDevicesLocked(outDevices);
956}
957
958void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
959 mReader->dispatchExternalStylusState(state);
960}
961
Michael Wrightd02c5b62014-02-10 15:10:22 -0800962InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
963 return mReader->mPolicy.get();
964}
965
966InputListenerInterface* InputReader::ContextImpl::getListener() {
967 return mReader->mQueuedListener.get();
968}
969
970EventHubInterface* InputReader::ContextImpl::getEventHub() {
971 return mReader->mEventHub.get();
972}
973
Prabir Pradhan42611e02018-11-27 14:04:02 -0800974uint32_t InputReader::ContextImpl::getNextSequenceNum() {
975 return (mReader->mNextSequenceNum)++;
976}
Michael Wrightd02c5b62014-02-10 15:10:22 -0800977
Michael Wrightd02c5b62014-02-10 15:10:22 -0800978// --- InputDevice ---
979
980InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
981 int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
982 mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
983 mIdentifier(identifier), mClasses(classes),
Tim Kilbourn063ff532015-04-08 10:26:18 -0700984 mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800985}
986
987InputDevice::~InputDevice() {
988 size_t numMappers = mMappers.size();
989 for (size_t i = 0; i < numMappers; i++) {
990 delete mMappers[i];
991 }
992 mMappers.clear();
993}
994
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700995bool InputDevice::isEnabled() {
996 return getEventHub()->isDeviceEnabled(mId);
997}
998
999void InputDevice::setEnabled(bool enabled, nsecs_t when) {
1000 if (isEnabled() == enabled) {
1001 return;
1002 }
1003
1004 if (enabled) {
1005 getEventHub()->enableDevice(mId);
1006 reset(when);
1007 } else {
1008 reset(when);
1009 getEventHub()->disableDevice(mId);
1010 }
1011 // Must change generation to flag this device as changed
1012 bumpGeneration();
1013}
1014
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001015void InputDevice::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001016 InputDeviceInfo deviceInfo;
Siarhei Vishniakoucd7ac1e2018-10-15 13:39:50 -07001017 getDeviceInfo(&deviceInfo);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001018
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001019 dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001020 deviceInfo.getDisplayName().c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001021 dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
1022 dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07001023 dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
1024 if (mAssociatedDisplayPort) {
1025 dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
1026 } else {
1027 dump += "<none>\n";
1028 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001029 dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
1030 dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
1031 dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001032
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001033 const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
1034 if (!ranges.empty()) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001035 dump += INDENT2 "Motion Ranges:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08001036 for (size_t i = 0; i < ranges.size(); i++) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001037 const InputDeviceInfo::MotionRange& range = ranges[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08001038 const char* label = getAxisLabel(range.axis);
1039 char name[32];
1040 if (label) {
1041 strncpy(name, label, sizeof(name));
1042 name[sizeof(name) - 1] = '\0';
1043 } else {
1044 snprintf(name, sizeof(name), "%d", range.axis);
1045 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001046 dump += StringPrintf(INDENT3 "%s: source=0x%08x, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08001047 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
1048 name, range.source, range.min, range.max, range.flat, range.fuzz,
1049 range.resolution);
1050 }
1051 }
1052
1053 size_t numMappers = mMappers.size();
1054 for (size_t i = 0; i < numMappers; i++) {
1055 InputMapper* mapper = mMappers[i];
1056 mapper->dump(dump);
1057 }
1058}
1059
1060void InputDevice::addMapper(InputMapper* mapper) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001061 mMappers.push_back(mapper);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001062}
1063
1064void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
1065 mSources = 0;
1066
1067 if (!isIgnored()) {
1068 if (!changes) { // first time only
1069 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
1070 }
1071
1072 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
1073 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
1074 sp<KeyCharacterMap> keyboardLayout =
1075 mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
1076 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
1077 bumpGeneration();
1078 }
1079 }
1080 }
1081
1082 if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
1083 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001084 std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001085 if (mAlias != alias) {
1086 mAlias = alias;
1087 bumpGeneration();
1088 }
1089 }
1090 }
1091
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001092 if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
Pin-Yu Huang2d8cc892019-07-19 04:00:44 +00001093 ssize_t index = config->disabledDevices.indexOf(mId);
1094 bool enabled = index < 0;
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001095 setEnabled(enabled, when);
1096 }
1097
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07001098 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
1099 // In most situations, no port will be specified.
1100 mAssociatedDisplayPort = std::nullopt;
1101 // Find the display port that corresponds to the current input port.
1102 const std::string& inputPort = mIdentifier.location;
1103 if (!inputPort.empty()) {
1104 const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
1105 const auto& displayPort = ports.find(inputPort);
1106 if (displayPort != ports.end()) {
1107 mAssociatedDisplayPort = std::make_optional(displayPort->second);
1108 }
1109 }
1110 }
1111
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001112 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001113 mapper->configure(when, config, changes);
1114 mSources |= mapper->getSources();
1115 }
1116 }
1117}
1118
1119void InputDevice::reset(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001120 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001121 mapper->reset(when);
1122 }
1123
1124 mContext->updateGlobalMetaState();
1125
1126 notifyReset(when);
1127}
1128
1129void InputDevice::process(const RawEvent* rawEvents, size_t count) {
1130 // Process all of the events in order for each mapper.
1131 // We cannot simply ask each mapper to process them in bulk because mappers may
1132 // have side-effects that must be interleaved. For example, joystick movement events and
1133 // gamepad button presses are handled by different mappers but they should be dispatched
1134 // in the order received.
Ivan Lozano96f12992017-11-09 14:45:38 -08001135 for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001136#if DEBUG_RAW_EVENTS
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07001137 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08001138 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
1139 rawEvent->when);
1140#endif
1141
1142 if (mDropUntilNextSync) {
1143 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1144 mDropUntilNextSync = false;
1145#if DEBUG_RAW_EVENTS
1146 ALOGD("Recovered from input event buffer overrun.");
1147#endif
1148 } else {
1149#if DEBUG_RAW_EVENTS
1150 ALOGD("Dropped input event while waiting for next input sync.");
1151#endif
1152 }
1153 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001154 ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001155 mDropUntilNextSync = true;
1156 reset(rawEvent->when);
1157 } else {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001158 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001159 mapper->process(rawEvent);
1160 }
1161 }
Ivan Lozano96f12992017-11-09 14:45:38 -08001162 --count;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001163 }
1164}
1165
1166void InputDevice::timeoutExpired(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001167 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001168 mapper->timeoutExpired(when);
1169 }
1170}
1171
Michael Wright842500e2015-03-13 17:32:02 -07001172void InputDevice::updateExternalStylusState(const StylusState& state) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001173 for (InputMapper* mapper : mMappers) {
Michael Wright842500e2015-03-13 17:32:02 -07001174 mapper->updateExternalStylusState(state);
1175 }
1176}
1177
Michael Wrightd02c5b62014-02-10 15:10:22 -08001178void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
1179 outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
Tim Kilbourn063ff532015-04-08 10:26:18 -07001180 mIsExternal, mHasMic);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001181 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001182 mapper->populateDeviceInfo(outDeviceInfo);
1183 }
1184}
1185
1186int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1187 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
1188}
1189
1190int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1191 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
1192}
1193
1194int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1195 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
1196}
1197
1198int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
1199 int32_t result = AKEY_STATE_UNKNOWN;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001200 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001201 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1202 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
1203 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
1204 int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
1205 if (currentResult >= AKEY_STATE_DOWN) {
1206 return currentResult;
1207 } else if (currentResult == AKEY_STATE_UP) {
1208 result = currentResult;
1209 }
1210 }
1211 }
1212 return result;
1213}
1214
1215bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1216 const int32_t* keyCodes, uint8_t* outFlags) {
1217 bool result = false;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001218 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001219 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1220 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1221 }
1222 }
1223 return result;
1224}
1225
1226void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1227 int32_t token) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001228 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001229 mapper->vibrate(pattern, patternSize, repeat, token);
1230 }
1231}
1232
1233void InputDevice::cancelVibrate(int32_t token) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001234 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001235 mapper->cancelVibrate(token);
1236 }
1237}
1238
Jeff Brownc9aa6282015-02-11 19:03:28 -08001239void InputDevice::cancelTouch(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001240 for (InputMapper* mapper : mMappers) {
Jeff Brownc9aa6282015-02-11 19:03:28 -08001241 mapper->cancelTouch(when);
1242 }
1243}
1244
Michael Wrightd02c5b62014-02-10 15:10:22 -08001245int32_t InputDevice::getMetaState() {
1246 int32_t result = 0;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001247 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001248 result |= mapper->getMetaState();
1249 }
1250 return result;
1251}
1252
Andrii Kulian763a3a42016-03-08 10:46:16 -08001253void InputDevice::updateMetaState(int32_t keyCode) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001254 for (InputMapper* mapper : mMappers) {
1255 mapper->updateMetaState(keyCode);
Andrii Kulian763a3a42016-03-08 10:46:16 -08001256 }
1257}
1258
Michael Wrightd02c5b62014-02-10 15:10:22 -08001259void InputDevice::fadePointer() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001260 for (InputMapper* mapper : mMappers) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001261 mapper->fadePointer();
1262 }
1263}
1264
1265void InputDevice::bumpGeneration() {
1266 mGeneration = mContext->bumpGeneration();
1267}
1268
1269void InputDevice::notifyReset(nsecs_t when) {
Prabir Pradhan42611e02018-11-27 14:04:02 -08001270 NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001271 mContext->getListener()->notifyDeviceReset(&args);
1272}
1273
Arthur Hungc23540e2018-11-29 20:42:11 +08001274std::optional<int32_t> InputDevice::getAssociatedDisplay() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08001275 for (InputMapper* mapper : mMappers) {
Arthur Hungc23540e2018-11-29 20:42:11 +08001276 std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
1277 if (associatedDisplayId) {
1278 return associatedDisplayId;
1279 }
1280 }
1281
1282 return std::nullopt;
1283}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001284
1285// --- CursorButtonAccumulator ---
1286
1287CursorButtonAccumulator::CursorButtonAccumulator() {
1288 clearButtons();
1289}
1290
1291void CursorButtonAccumulator::reset(InputDevice* device) {
1292 mBtnLeft = device->isKeyPressed(BTN_LEFT);
1293 mBtnRight = device->isKeyPressed(BTN_RIGHT);
1294 mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
1295 mBtnBack = device->isKeyPressed(BTN_BACK);
1296 mBtnSide = device->isKeyPressed(BTN_SIDE);
1297 mBtnForward = device->isKeyPressed(BTN_FORWARD);
1298 mBtnExtra = device->isKeyPressed(BTN_EXTRA);
1299 mBtnTask = device->isKeyPressed(BTN_TASK);
1300}
1301
1302void CursorButtonAccumulator::clearButtons() {
1303 mBtnLeft = 0;
1304 mBtnRight = 0;
1305 mBtnMiddle = 0;
1306 mBtnBack = 0;
1307 mBtnSide = 0;
1308 mBtnForward = 0;
1309 mBtnExtra = 0;
1310 mBtnTask = 0;
1311}
1312
1313void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1314 if (rawEvent->type == EV_KEY) {
1315 switch (rawEvent->code) {
1316 case BTN_LEFT:
1317 mBtnLeft = rawEvent->value;
1318 break;
1319 case BTN_RIGHT:
1320 mBtnRight = rawEvent->value;
1321 break;
1322 case BTN_MIDDLE:
1323 mBtnMiddle = rawEvent->value;
1324 break;
1325 case BTN_BACK:
1326 mBtnBack = rawEvent->value;
1327 break;
1328 case BTN_SIDE:
1329 mBtnSide = rawEvent->value;
1330 break;
1331 case BTN_FORWARD:
1332 mBtnForward = rawEvent->value;
1333 break;
1334 case BTN_EXTRA:
1335 mBtnExtra = rawEvent->value;
1336 break;
1337 case BTN_TASK:
1338 mBtnTask = rawEvent->value;
1339 break;
1340 }
1341 }
1342}
1343
1344uint32_t CursorButtonAccumulator::getButtonState() const {
1345 uint32_t result = 0;
1346 if (mBtnLeft) {
1347 result |= AMOTION_EVENT_BUTTON_PRIMARY;
1348 }
1349 if (mBtnRight) {
1350 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1351 }
1352 if (mBtnMiddle) {
1353 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1354 }
1355 if (mBtnBack || mBtnSide) {
1356 result |= AMOTION_EVENT_BUTTON_BACK;
1357 }
1358 if (mBtnForward || mBtnExtra) {
1359 result |= AMOTION_EVENT_BUTTON_FORWARD;
1360 }
1361 return result;
1362}
1363
1364
1365// --- CursorMotionAccumulator ---
1366
1367CursorMotionAccumulator::CursorMotionAccumulator() {
1368 clearRelativeAxes();
1369}
1370
1371void CursorMotionAccumulator::reset(InputDevice* device) {
1372 clearRelativeAxes();
1373}
1374
1375void CursorMotionAccumulator::clearRelativeAxes() {
1376 mRelX = 0;
1377 mRelY = 0;
1378}
1379
1380void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1381 if (rawEvent->type == EV_REL) {
1382 switch (rawEvent->code) {
1383 case REL_X:
1384 mRelX = rawEvent->value;
1385 break;
1386 case REL_Y:
1387 mRelY = rawEvent->value;
1388 break;
1389 }
1390 }
1391}
1392
1393void CursorMotionAccumulator::finishSync() {
1394 clearRelativeAxes();
1395}
1396
1397
1398// --- CursorScrollAccumulator ---
1399
1400CursorScrollAccumulator::CursorScrollAccumulator() :
1401 mHaveRelWheel(false), mHaveRelHWheel(false) {
1402 clearRelativeAxes();
1403}
1404
1405void CursorScrollAccumulator::configure(InputDevice* device) {
1406 mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1407 mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1408}
1409
1410void CursorScrollAccumulator::reset(InputDevice* device) {
1411 clearRelativeAxes();
1412}
1413
1414void CursorScrollAccumulator::clearRelativeAxes() {
1415 mRelWheel = 0;
1416 mRelHWheel = 0;
1417}
1418
1419void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
1420 if (rawEvent->type == EV_REL) {
1421 switch (rawEvent->code) {
1422 case REL_WHEEL:
1423 mRelWheel = rawEvent->value;
1424 break;
1425 case REL_HWHEEL:
1426 mRelHWheel = rawEvent->value;
1427 break;
1428 }
1429 }
1430}
1431
1432void CursorScrollAccumulator::finishSync() {
1433 clearRelativeAxes();
1434}
1435
1436
1437// --- TouchButtonAccumulator ---
1438
1439TouchButtonAccumulator::TouchButtonAccumulator() :
1440 mHaveBtnTouch(false), mHaveStylus(false) {
1441 clearButtons();
1442}
1443
1444void TouchButtonAccumulator::configure(InputDevice* device) {
1445 mHaveBtnTouch = device->hasKey(BTN_TOUCH);
1446 mHaveStylus = device->hasKey(BTN_TOOL_PEN)
1447 || device->hasKey(BTN_TOOL_RUBBER)
1448 || device->hasKey(BTN_TOOL_BRUSH)
1449 || device->hasKey(BTN_TOOL_PENCIL)
1450 || device->hasKey(BTN_TOOL_AIRBRUSH);
1451}
1452
1453void TouchButtonAccumulator::reset(InputDevice* device) {
1454 mBtnTouch = device->isKeyPressed(BTN_TOUCH);
1455 mBtnStylus = device->isKeyPressed(BTN_STYLUS);
Michael Wright842500e2015-03-13 17:32:02 -07001456 // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
1457 mBtnStylus2 =
1458 device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001459 mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
1460 mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
1461 mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
1462 mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
1463 mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
1464 mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
1465 mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
1466 mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
1467 mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
1468 mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
1469 mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
1470}
1471
1472void TouchButtonAccumulator::clearButtons() {
1473 mBtnTouch = 0;
1474 mBtnStylus = 0;
1475 mBtnStylus2 = 0;
1476 mBtnToolFinger = 0;
1477 mBtnToolPen = 0;
1478 mBtnToolRubber = 0;
1479 mBtnToolBrush = 0;
1480 mBtnToolPencil = 0;
1481 mBtnToolAirbrush = 0;
1482 mBtnToolMouse = 0;
1483 mBtnToolLens = 0;
1484 mBtnToolDoubleTap = 0;
1485 mBtnToolTripleTap = 0;
1486 mBtnToolQuadTap = 0;
1487}
1488
1489void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1490 if (rawEvent->type == EV_KEY) {
1491 switch (rawEvent->code) {
1492 case BTN_TOUCH:
1493 mBtnTouch = rawEvent->value;
1494 break;
1495 case BTN_STYLUS:
1496 mBtnStylus = rawEvent->value;
1497 break;
1498 case BTN_STYLUS2:
Michael Wright842500e2015-03-13 17:32:02 -07001499 case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
Michael Wrightd02c5b62014-02-10 15:10:22 -08001500 mBtnStylus2 = rawEvent->value;
1501 break;
1502 case BTN_TOOL_FINGER:
1503 mBtnToolFinger = rawEvent->value;
1504 break;
1505 case BTN_TOOL_PEN:
1506 mBtnToolPen = rawEvent->value;
1507 break;
1508 case BTN_TOOL_RUBBER:
1509 mBtnToolRubber = rawEvent->value;
1510 break;
1511 case BTN_TOOL_BRUSH:
1512 mBtnToolBrush = rawEvent->value;
1513 break;
1514 case BTN_TOOL_PENCIL:
1515 mBtnToolPencil = rawEvent->value;
1516 break;
1517 case BTN_TOOL_AIRBRUSH:
1518 mBtnToolAirbrush = rawEvent->value;
1519 break;
1520 case BTN_TOOL_MOUSE:
1521 mBtnToolMouse = rawEvent->value;
1522 break;
1523 case BTN_TOOL_LENS:
1524 mBtnToolLens = rawEvent->value;
1525 break;
1526 case BTN_TOOL_DOUBLETAP:
1527 mBtnToolDoubleTap = rawEvent->value;
1528 break;
1529 case BTN_TOOL_TRIPLETAP:
1530 mBtnToolTripleTap = rawEvent->value;
1531 break;
1532 case BTN_TOOL_QUADTAP:
1533 mBtnToolQuadTap = rawEvent->value;
1534 break;
1535 }
1536 }
1537}
1538
1539uint32_t TouchButtonAccumulator::getButtonState() const {
1540 uint32_t result = 0;
1541 if (mBtnStylus) {
Michael Wright7b159c92015-05-14 14:48:03 +01001542 result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001543 }
1544 if (mBtnStylus2) {
Michael Wright7b159c92015-05-14 14:48:03 +01001545 result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001546 }
1547 return result;
1548}
1549
1550int32_t TouchButtonAccumulator::getToolType() const {
1551 if (mBtnToolMouse || mBtnToolLens) {
1552 return AMOTION_EVENT_TOOL_TYPE_MOUSE;
1553 }
1554 if (mBtnToolRubber) {
1555 return AMOTION_EVENT_TOOL_TYPE_ERASER;
1556 }
1557 if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
1558 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1559 }
1560 if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
1561 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1562 }
1563 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1564}
1565
1566bool TouchButtonAccumulator::isToolActive() const {
1567 return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
1568 || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
1569 || mBtnToolMouse || mBtnToolLens
1570 || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
1571}
1572
1573bool TouchButtonAccumulator::isHovering() const {
1574 return mHaveBtnTouch && !mBtnTouch;
1575}
1576
1577bool TouchButtonAccumulator::hasStylus() const {
1578 return mHaveStylus;
1579}
1580
1581
1582// --- RawPointerAxes ---
1583
1584RawPointerAxes::RawPointerAxes() {
1585 clear();
1586}
1587
1588void RawPointerAxes::clear() {
1589 x.clear();
1590 y.clear();
1591 pressure.clear();
1592 touchMajor.clear();
1593 touchMinor.clear();
1594 toolMajor.clear();
1595 toolMinor.clear();
1596 orientation.clear();
1597 distance.clear();
1598 tiltX.clear();
1599 tiltY.clear();
1600 trackingId.clear();
1601 slot.clear();
1602}
1603
1604
1605// --- RawPointerData ---
1606
1607RawPointerData::RawPointerData() {
1608 clear();
1609}
1610
1611void RawPointerData::clear() {
1612 pointerCount = 0;
1613 clearIdBits();
1614}
1615
1616void RawPointerData::copyFrom(const RawPointerData& other) {
1617 pointerCount = other.pointerCount;
1618 hoveringIdBits = other.hoveringIdBits;
1619 touchingIdBits = other.touchingIdBits;
1620
1621 for (uint32_t i = 0; i < pointerCount; i++) {
1622 pointers[i] = other.pointers[i];
1623
1624 int id = pointers[i].id;
1625 idToIndex[id] = other.idToIndex[id];
1626 }
1627}
1628
1629void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
1630 float x = 0, y = 0;
1631 uint32_t count = touchingIdBits.count();
1632 if (count) {
1633 for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
1634 uint32_t id = idBits.clearFirstMarkedBit();
1635 const Pointer& pointer = pointerForId(id);
1636 x += pointer.x;
1637 y += pointer.y;
1638 }
1639 x /= count;
1640 y /= count;
1641 }
1642 *outX = x;
1643 *outY = y;
1644}
1645
1646
1647// --- CookedPointerData ---
1648
1649CookedPointerData::CookedPointerData() {
1650 clear();
1651}
1652
1653void CookedPointerData::clear() {
1654 pointerCount = 0;
1655 hoveringIdBits.clear();
1656 touchingIdBits.clear();
1657}
1658
1659void CookedPointerData::copyFrom(const CookedPointerData& other) {
1660 pointerCount = other.pointerCount;
1661 hoveringIdBits = other.hoveringIdBits;
1662 touchingIdBits = other.touchingIdBits;
1663
1664 for (uint32_t i = 0; i < pointerCount; i++) {
1665 pointerProperties[i].copyFrom(other.pointerProperties[i]);
1666 pointerCoords[i].copyFrom(other.pointerCoords[i]);
1667
1668 int id = pointerProperties[i].id;
1669 idToIndex[id] = other.idToIndex[id];
1670 }
1671}
1672
1673
1674// --- SingleTouchMotionAccumulator ---
1675
1676SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1677 clearAbsoluteAxes();
1678}
1679
1680void SingleTouchMotionAccumulator::reset(InputDevice* device) {
1681 mAbsX = device->getAbsoluteAxisValue(ABS_X);
1682 mAbsY = device->getAbsoluteAxisValue(ABS_Y);
1683 mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
1684 mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
1685 mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
1686 mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
1687 mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
1688}
1689
1690void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1691 mAbsX = 0;
1692 mAbsY = 0;
1693 mAbsPressure = 0;
1694 mAbsToolWidth = 0;
1695 mAbsDistance = 0;
1696 mAbsTiltX = 0;
1697 mAbsTiltY = 0;
1698}
1699
1700void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1701 if (rawEvent->type == EV_ABS) {
1702 switch (rawEvent->code) {
1703 case ABS_X:
1704 mAbsX = rawEvent->value;
1705 break;
1706 case ABS_Y:
1707 mAbsY = rawEvent->value;
1708 break;
1709 case ABS_PRESSURE:
1710 mAbsPressure = rawEvent->value;
1711 break;
1712 case ABS_TOOL_WIDTH:
1713 mAbsToolWidth = rawEvent->value;
1714 break;
1715 case ABS_DISTANCE:
1716 mAbsDistance = rawEvent->value;
1717 break;
1718 case ABS_TILT_X:
1719 mAbsTiltX = rawEvent->value;
1720 break;
1721 case ABS_TILT_Y:
1722 mAbsTiltY = rawEvent->value;
1723 break;
1724 }
1725 }
1726}
1727
1728
1729// --- MultiTouchMotionAccumulator ---
1730
Atif Niyaz21da0ff2019-06-28 13:22:51 -07001731MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
1732 : mCurrentSlot(-1),
1733 mSlots(nullptr),
1734 mSlotCount(0),
1735 mUsingSlotsProtocol(false),
1736 mHaveStylus(false) {}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001737
1738MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1739 delete[] mSlots;
1740}
1741
1742void MultiTouchMotionAccumulator::configure(InputDevice* device,
1743 size_t slotCount, bool usingSlotsProtocol) {
1744 mSlotCount = slotCount;
1745 mUsingSlotsProtocol = usingSlotsProtocol;
1746 mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
1747
1748 delete[] mSlots;
1749 mSlots = new Slot[slotCount];
1750}
1751
1752void MultiTouchMotionAccumulator::reset(InputDevice* device) {
1753 // Unfortunately there is no way to read the initial contents of the slots.
1754 // So when we reset the accumulator, we must assume they are all zeroes.
1755 if (mUsingSlotsProtocol) {
1756 // Query the driver for the current slot index and use it as the initial slot
1757 // before we start reading events from the device. It is possible that the
1758 // current slot index will not be the same as it was when the first event was
1759 // written into the evdev buffer, which means the input mapper could start
1760 // out of sync with the initial state of the events in the evdev buffer.
1761 // In the extremely unlikely case that this happens, the data from
1762 // two slots will be confused until the next ABS_MT_SLOT event is received.
1763 // This can cause the touch point to "jump", but at least there will be
1764 // no stuck touches.
1765 int32_t initialSlot;
1766 status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
1767 ABS_MT_SLOT, &initialSlot);
1768 if (status) {
1769 ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
1770 initialSlot = -1;
1771 }
1772 clearSlots(initialSlot);
1773 } else {
1774 clearSlots(-1);
1775 }
1776}
1777
1778void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
1779 if (mSlots) {
1780 for (size_t i = 0; i < mSlotCount; i++) {
1781 mSlots[i].clear();
1782 }
1783 }
1784 mCurrentSlot = initialSlot;
1785}
1786
1787void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1788 if (rawEvent->type == EV_ABS) {
1789 bool newSlot = false;
1790 if (mUsingSlotsProtocol) {
1791 if (rawEvent->code == ABS_MT_SLOT) {
1792 mCurrentSlot = rawEvent->value;
1793 newSlot = true;
1794 }
1795 } else if (mCurrentSlot < 0) {
1796 mCurrentSlot = 0;
1797 }
1798
1799 if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1800#if DEBUG_POINTERS
1801 if (newSlot) {
1802 ALOGW("MultiTouch device emitted invalid slot index %d but it "
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07001803 "should be between 0 and %zd; ignoring this slot.",
Michael Wrightd02c5b62014-02-10 15:10:22 -08001804 mCurrentSlot, mSlotCount - 1);
1805 }
1806#endif
1807 } else {
1808 Slot* slot = &mSlots[mCurrentSlot];
1809
1810 switch (rawEvent->code) {
1811 case ABS_MT_POSITION_X:
1812 slot->mInUse = true;
1813 slot->mAbsMTPositionX = rawEvent->value;
1814 break;
1815 case ABS_MT_POSITION_Y:
1816 slot->mInUse = true;
1817 slot->mAbsMTPositionY = rawEvent->value;
1818 break;
1819 case ABS_MT_TOUCH_MAJOR:
1820 slot->mInUse = true;
1821 slot->mAbsMTTouchMajor = rawEvent->value;
1822 break;
1823 case ABS_MT_TOUCH_MINOR:
1824 slot->mInUse = true;
1825 slot->mAbsMTTouchMinor = rawEvent->value;
1826 slot->mHaveAbsMTTouchMinor = true;
1827 break;
1828 case ABS_MT_WIDTH_MAJOR:
1829 slot->mInUse = true;
1830 slot->mAbsMTWidthMajor = rawEvent->value;
1831 break;
1832 case ABS_MT_WIDTH_MINOR:
1833 slot->mInUse = true;
1834 slot->mAbsMTWidthMinor = rawEvent->value;
1835 slot->mHaveAbsMTWidthMinor = true;
1836 break;
1837 case ABS_MT_ORIENTATION:
1838 slot->mInUse = true;
1839 slot->mAbsMTOrientation = rawEvent->value;
1840 break;
1841 case ABS_MT_TRACKING_ID:
1842 if (mUsingSlotsProtocol && rawEvent->value < 0) {
1843 // The slot is no longer in use but it retains its previous contents,
1844 // which may be reused for subsequent touches.
1845 slot->mInUse = false;
1846 } else {
1847 slot->mInUse = true;
1848 slot->mAbsMTTrackingId = rawEvent->value;
1849 }
1850 break;
1851 case ABS_MT_PRESSURE:
1852 slot->mInUse = true;
1853 slot->mAbsMTPressure = rawEvent->value;
1854 break;
1855 case ABS_MT_DISTANCE:
1856 slot->mInUse = true;
1857 slot->mAbsMTDistance = rawEvent->value;
1858 break;
1859 case ABS_MT_TOOL_TYPE:
1860 slot->mInUse = true;
1861 slot->mAbsMTToolType = rawEvent->value;
1862 slot->mHaveAbsMTToolType = true;
1863 break;
1864 }
1865 }
1866 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
1867 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1868 mCurrentSlot += 1;
1869 }
1870}
1871
1872void MultiTouchMotionAccumulator::finishSync() {
1873 if (!mUsingSlotsProtocol) {
1874 clearSlots(-1);
1875 }
1876}
1877
1878bool MultiTouchMotionAccumulator::hasStylus() const {
1879 return mHaveStylus;
1880}
1881
1882
1883// --- MultiTouchMotionAccumulator::Slot ---
1884
1885MultiTouchMotionAccumulator::Slot::Slot() {
1886 clear();
1887}
1888
1889void MultiTouchMotionAccumulator::Slot::clear() {
1890 mInUse = false;
1891 mHaveAbsMTTouchMinor = false;
1892 mHaveAbsMTWidthMinor = false;
1893 mHaveAbsMTToolType = false;
1894 mAbsMTPositionX = 0;
1895 mAbsMTPositionY = 0;
1896 mAbsMTTouchMajor = 0;
1897 mAbsMTTouchMinor = 0;
1898 mAbsMTWidthMajor = 0;
1899 mAbsMTWidthMinor = 0;
1900 mAbsMTOrientation = 0;
1901 mAbsMTTrackingId = -1;
1902 mAbsMTPressure = 0;
1903 mAbsMTDistance = 0;
1904 mAbsMTToolType = 0;
1905}
1906
1907int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1908 if (mHaveAbsMTToolType) {
1909 switch (mAbsMTToolType) {
1910 case MT_TOOL_FINGER:
1911 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1912 case MT_TOOL_PEN:
1913 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1914 }
1915 }
1916 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1917}
1918
1919
1920// --- InputMapper ---
1921
1922InputMapper::InputMapper(InputDevice* device) :
1923 mDevice(device), mContext(device->getContext()) {
1924}
1925
1926InputMapper::~InputMapper() {
1927}
1928
1929void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1930 info->addSource(getSources());
1931}
1932
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001933void InputMapper::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001934}
1935
1936void InputMapper::configure(nsecs_t when,
1937 const InputReaderConfiguration* config, uint32_t changes) {
1938}
1939
1940void InputMapper::reset(nsecs_t when) {
1941}
1942
1943void InputMapper::timeoutExpired(nsecs_t when) {
1944}
1945
1946int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1947 return AKEY_STATE_UNKNOWN;
1948}
1949
1950int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1951 return AKEY_STATE_UNKNOWN;
1952}
1953
1954int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1955 return AKEY_STATE_UNKNOWN;
1956}
1957
1958bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1959 const int32_t* keyCodes, uint8_t* outFlags) {
1960 return false;
1961}
1962
1963void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1964 int32_t token) {
1965}
1966
1967void InputMapper::cancelVibrate(int32_t token) {
1968}
1969
Jeff Brownc9aa6282015-02-11 19:03:28 -08001970void InputMapper::cancelTouch(nsecs_t when) {
1971}
1972
Michael Wrightd02c5b62014-02-10 15:10:22 -08001973int32_t InputMapper::getMetaState() {
1974 return 0;
1975}
1976
Andrii Kulian763a3a42016-03-08 10:46:16 -08001977void InputMapper::updateMetaState(int32_t keyCode) {
1978}
1979
Michael Wright842500e2015-03-13 17:32:02 -07001980void InputMapper::updateExternalStylusState(const StylusState& state) {
1981
1982}
1983
Michael Wrightd02c5b62014-02-10 15:10:22 -08001984void InputMapper::fadePointer() {
1985}
1986
1987status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
1988 return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
1989}
1990
1991void InputMapper::bumpGeneration() {
1992 mDevice->bumpGeneration();
1993}
1994
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001995void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump,
Michael Wrightd02c5b62014-02-10 15:10:22 -08001996 const RawAbsoluteAxisInfo& axis, const char* name) {
1997 if (axis.valid) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001998 dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08001999 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
2000 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002001 dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002002 }
2003}
2004
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002005void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
2006 dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
2007 dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
2008 dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
2009 dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
Michael Wright842500e2015-03-13 17:32:02 -07002010}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002011
2012// --- SwitchInputMapper ---
2013
2014SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002015 InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002016}
2017
2018SwitchInputMapper::~SwitchInputMapper() {
2019}
2020
2021uint32_t SwitchInputMapper::getSources() {
2022 return AINPUT_SOURCE_SWITCH;
2023}
2024
2025void SwitchInputMapper::process(const RawEvent* rawEvent) {
2026 switch (rawEvent->type) {
2027 case EV_SW:
2028 processSwitch(rawEvent->code, rawEvent->value);
2029 break;
2030
2031 case EV_SYN:
2032 if (rawEvent->code == SYN_REPORT) {
2033 sync(rawEvent->when);
2034 }
2035 }
2036}
2037
2038void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
2039 if (switchCode >= 0 && switchCode < 32) {
2040 if (switchValue) {
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002041 mSwitchValues |= 1 << switchCode;
2042 } else {
2043 mSwitchValues &= ~(1 << switchCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002044 }
2045 mUpdatedSwitchMask |= 1 << switchCode;
2046 }
2047}
2048
2049void SwitchInputMapper::sync(nsecs_t when) {
2050 if (mUpdatedSwitchMask) {
Michael Wright3da3b842014-08-29 16:16:26 -07002051 uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
Prabir Pradhan42611e02018-11-27 14:04:02 -08002052 NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
2053 mUpdatedSwitchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002054 getListener()->notifySwitch(&args);
2055
Michael Wrightd02c5b62014-02-10 15:10:22 -08002056 mUpdatedSwitchMask = 0;
2057 }
2058}
2059
2060int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
2061 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
2062}
2063
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002064void SwitchInputMapper::dump(std::string& dump) {
2065 dump += INDENT2 "Switch Input Mapper:\n";
2066 dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002067}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002068
2069// --- VibratorInputMapper ---
2070
2071VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
2072 InputMapper(device), mVibrating(false) {
2073}
2074
2075VibratorInputMapper::~VibratorInputMapper() {
2076}
2077
2078uint32_t VibratorInputMapper::getSources() {
2079 return 0;
2080}
2081
2082void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2083 InputMapper::populateDeviceInfo(info);
2084
2085 info->setVibrator(true);
2086}
2087
2088void VibratorInputMapper::process(const RawEvent* rawEvent) {
2089 // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
2090}
2091
2092void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
2093 int32_t token) {
2094#if DEBUG_VIBRATOR
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002095 std::string patternStr;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002096 for (size_t i = 0; i < patternSize; i++) {
2097 if (i != 0) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002098 patternStr += ", ";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002099 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002100 patternStr += StringPrintf("%" PRId64, pattern[i]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002101 }
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07002102 ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002103 getDeviceId(), patternStr.c_str(), repeat, token);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002104#endif
2105
2106 mVibrating = true;
2107 memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
2108 mPatternSize = patternSize;
2109 mRepeat = repeat;
2110 mToken = token;
2111 mIndex = -1;
2112
2113 nextStep();
2114}
2115
2116void VibratorInputMapper::cancelVibrate(int32_t token) {
2117#if DEBUG_VIBRATOR
2118 ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
2119#endif
2120
2121 if (mVibrating && mToken == token) {
2122 stopVibrating();
2123 }
2124}
2125
2126void VibratorInputMapper::timeoutExpired(nsecs_t when) {
2127 if (mVibrating) {
2128 if (when >= mNextStepTime) {
2129 nextStep();
2130 } else {
2131 getContext()->requestTimeoutAtTime(mNextStepTime);
2132 }
2133 }
2134}
2135
2136void VibratorInputMapper::nextStep() {
2137 mIndex += 1;
2138 if (size_t(mIndex) >= mPatternSize) {
2139 if (mRepeat < 0) {
2140 // We are done.
2141 stopVibrating();
2142 return;
2143 }
2144 mIndex = mRepeat;
2145 }
2146
2147 bool vibratorOn = mIndex & 1;
2148 nsecs_t duration = mPattern[mIndex];
2149 if (vibratorOn) {
2150#if DEBUG_VIBRATOR
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07002151 ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002152#endif
2153 getEventHub()->vibrate(getDeviceId(), duration);
2154 } else {
2155#if DEBUG_VIBRATOR
2156 ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
2157#endif
2158 getEventHub()->cancelVibrate(getDeviceId());
2159 }
2160 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
2161 mNextStepTime = now + duration;
2162 getContext()->requestTimeoutAtTime(mNextStepTime);
2163#if DEBUG_VIBRATOR
2164 ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
2165#endif
2166}
2167
2168void VibratorInputMapper::stopVibrating() {
2169 mVibrating = false;
2170#if DEBUG_VIBRATOR
2171 ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
2172#endif
2173 getEventHub()->cancelVibrate(getDeviceId());
2174}
2175
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002176void VibratorInputMapper::dump(std::string& dump) {
2177 dump += INDENT2 "Vibrator Input Mapper:\n";
2178 dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002179}
2180
2181
2182// --- KeyboardInputMapper ---
2183
2184KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
2185 uint32_t source, int32_t keyboardType) :
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002186 InputMapper(device), mSource(source), mKeyboardType(keyboardType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002187}
2188
2189KeyboardInputMapper::~KeyboardInputMapper() {
2190}
2191
2192uint32_t KeyboardInputMapper::getSources() {
2193 return mSource;
2194}
2195
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002196int32_t KeyboardInputMapper::getOrientation() {
2197 if (mViewport) {
2198 return mViewport->orientation;
2199 }
2200 return DISPLAY_ORIENTATION_0;
2201}
2202
2203int32_t KeyboardInputMapper::getDisplayId() {
2204 if (mViewport) {
2205 return mViewport->displayId;
2206 }
2207 return ADISPLAY_ID_NONE;
2208}
2209
Michael Wrightd02c5b62014-02-10 15:10:22 -08002210void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2211 InputMapper::populateDeviceInfo(info);
2212
2213 info->setKeyboardType(mKeyboardType);
2214 info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
2215}
2216
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002217void KeyboardInputMapper::dump(std::string& dump) {
2218 dump += INDENT2 "Keyboard Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002219 dumpParameters(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002220 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002221 dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002222 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
2223 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
2224 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002225}
2226
Michael Wrightd02c5b62014-02-10 15:10:22 -08002227void KeyboardInputMapper::configure(nsecs_t when,
2228 const InputReaderConfiguration* config, uint32_t changes) {
2229 InputMapper::configure(when, config, changes);
2230
2231 if (!changes) { // first time only
2232 // Configure basic parameters.
2233 configureParameters();
2234 }
2235
2236 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002237 if (mParameters.orientationAware) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07002238 mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002239 }
2240 }
2241}
2242
Ivan Podogovb9afef32017-02-13 15:34:32 +00002243static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
2244 int32_t mapped = 0;
2245 if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
2246 for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
2247 if (stemKeyRotationMap[i][0] == keyCode) {
2248 stemKeyRotationMap[i][1] = mapped;
2249 return;
2250 }
2251 }
2252 }
2253}
2254
Michael Wrightd02c5b62014-02-10 15:10:22 -08002255void KeyboardInputMapper::configureParameters() {
2256 mParameters.orientationAware = false;
Ivan Podogovb9afef32017-02-13 15:34:32 +00002257 const PropertyMap& config = getDevice()->getConfiguration();
2258 config.tryGetProperty(String8("keyboard.orientationAware"),
Michael Wrightd02c5b62014-02-10 15:10:22 -08002259 mParameters.orientationAware);
2260
Michael Wrightd02c5b62014-02-10 15:10:22 -08002261 if (mParameters.orientationAware) {
Ivan Podogovb9afef32017-02-13 15:34:32 +00002262 mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
2263 mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
2264 mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
2265 mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
Michael Wrightd02c5b62014-02-10 15:10:22 -08002266 }
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002267
2268 mParameters.handlesKeyRepeat = false;
Ivan Podogovb9afef32017-02-13 15:34:32 +00002269 config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002270 mParameters.handlesKeyRepeat);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002271}
2272
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002273void KeyboardInputMapper::dumpParameters(std::string& dump) {
2274 dump += INDENT3 "Parameters:\n";
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002275 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002276 toString(mParameters.orientationAware));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002277 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n",
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002278 toString(mParameters.handlesKeyRepeat));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002279}
2280
2281void KeyboardInputMapper::reset(nsecs_t when) {
2282 mMetaState = AMETA_NONE;
2283 mDownTime = 0;
2284 mKeyDowns.clear();
2285 mCurrentHidUsage = 0;
2286
2287 resetLedState();
2288
2289 InputMapper::reset(when);
2290}
2291
2292void KeyboardInputMapper::process(const RawEvent* rawEvent) {
2293 switch (rawEvent->type) {
2294 case EV_KEY: {
2295 int32_t scanCode = rawEvent->code;
2296 int32_t usageCode = mCurrentHidUsage;
2297 mCurrentHidUsage = 0;
2298
2299 if (isKeyboardOrGamepadKey(scanCode)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002300 processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002301 }
2302 break;
2303 }
2304 case EV_MSC: {
2305 if (rawEvent->code == MSC_SCAN) {
2306 mCurrentHidUsage = rawEvent->value;
2307 }
2308 break;
2309 }
2310 case EV_SYN: {
2311 if (rawEvent->code == SYN_REPORT) {
2312 mCurrentHidUsage = 0;
2313 }
2314 }
2315 }
2316}
2317
2318bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
2319 return scanCode < BTN_MOUSE
2320 || scanCode >= KEY_OK
2321 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
2322 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
2323}
2324
Michael Wright58ba9882017-07-26 16:19:11 +01002325bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
2326 switch (keyCode) {
2327 case AKEYCODE_MEDIA_PLAY:
2328 case AKEYCODE_MEDIA_PAUSE:
2329 case AKEYCODE_MEDIA_PLAY_PAUSE:
2330 case AKEYCODE_MUTE:
2331 case AKEYCODE_HEADSETHOOK:
2332 case AKEYCODE_MEDIA_STOP:
2333 case AKEYCODE_MEDIA_NEXT:
2334 case AKEYCODE_MEDIA_PREVIOUS:
2335 case AKEYCODE_MEDIA_REWIND:
2336 case AKEYCODE_MEDIA_RECORD:
2337 case AKEYCODE_MEDIA_FAST_FORWARD:
2338 case AKEYCODE_MEDIA_SKIP_FORWARD:
2339 case AKEYCODE_MEDIA_SKIP_BACKWARD:
2340 case AKEYCODE_MEDIA_STEP_FORWARD:
2341 case AKEYCODE_MEDIA_STEP_BACKWARD:
2342 case AKEYCODE_MEDIA_AUDIO_TRACK:
2343 case AKEYCODE_VOLUME_UP:
2344 case AKEYCODE_VOLUME_DOWN:
2345 case AKEYCODE_VOLUME_MUTE:
2346 case AKEYCODE_TV_AUDIO_DESCRIPTION:
2347 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
2348 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
2349 return true;
2350 }
2351 return false;
2352}
2353
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002354void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
2355 int32_t usageCode) {
2356 int32_t keyCode;
2357 int32_t keyMetaState;
2358 uint32_t policyFlags;
2359
2360 if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
2361 &keyCode, &keyMetaState, &policyFlags)) {
2362 keyCode = AKEYCODE_UNKNOWN;
2363 keyMetaState = mMetaState;
2364 policyFlags = 0;
2365 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002366
2367 if (down) {
2368 // Rotate key codes according to orientation if needed.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002369 if (mParameters.orientationAware) {
2370 keyCode = rotateKeyCode(keyCode, getOrientation());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002371 }
2372
2373 // Add key down.
2374 ssize_t keyDownIndex = findKeyDown(scanCode);
2375 if (keyDownIndex >= 0) {
2376 // key repeat, be sure to use same keycode as before in case of rotation
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002377 keyCode = mKeyDowns[keyDownIndex].keyCode;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002378 } else {
2379 // key down
2380 if ((policyFlags & POLICY_FLAG_VIRTUAL)
2381 && mContext->shouldDropVirtualKey(when,
2382 getDevice(), keyCode, scanCode)) {
2383 return;
2384 }
Jeff Brownc9aa6282015-02-11 19:03:28 -08002385 if (policyFlags & POLICY_FLAG_GESTURE) {
2386 mDevice->cancelTouch(when);
2387 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002388
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002389 KeyDown keyDown;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002390 keyDown.keyCode = keyCode;
2391 keyDown.scanCode = scanCode;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002392 mKeyDowns.push_back(keyDown);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002393 }
2394
2395 mDownTime = when;
2396 } else {
2397 // Remove key down.
2398 ssize_t keyDownIndex = findKeyDown(scanCode);
2399 if (keyDownIndex >= 0) {
2400 // key up, be sure to use same keycode as before in case of rotation
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08002401 keyCode = mKeyDowns[keyDownIndex].keyCode;
2402 mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002403 } else {
2404 // key was not actually down
2405 ALOGI("Dropping key up from device %s because the key was not down. "
2406 "keyCode=%d, scanCode=%d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002407 getDeviceName().c_str(), keyCode, scanCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002408 return;
2409 }
2410 }
2411
Andrii Kulian763a3a42016-03-08 10:46:16 -08002412 if (updateMetaStateIfNeeded(keyCode, down)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002413 // If global meta state changed send it along with the key.
2414 // If it has not changed then we'll use what keymap gave us,
2415 // since key replacement logic might temporarily reset a few
2416 // meta bits for given key.
Andrii Kulian763a3a42016-03-08 10:46:16 -08002417 keyMetaState = mMetaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002418 }
2419
2420 nsecs_t downTime = mDownTime;
2421
2422 // Key down on external an keyboard should wake the device.
2423 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
2424 // For internal keyboards, the key layout file should specify the policy flags for
2425 // each wake key individually.
2426 // TODO: Use the input device configuration to control this behavior more finely.
Michael Wright58ba9882017-07-26 16:19:11 +01002427 if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
Michael Wright872db4f2014-04-22 15:03:51 -07002428 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002429 }
2430
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002431 if (mParameters.handlesKeyRepeat) {
2432 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
2433 }
2434
Prabir Pradhan42611e02018-11-27 14:04:02 -08002435 NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
2436 getDisplayId(), policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002437 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002438 getListener()->notifyKey(&args);
2439}
2440
2441ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
2442 size_t n = mKeyDowns.size();
2443 for (size_t i = 0; i < n; i++) {
2444 if (mKeyDowns[i].scanCode == scanCode) {
2445 return i;
2446 }
2447 }
2448 return -1;
2449}
2450
2451int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
2452 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
2453}
2454
2455int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2456 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2457}
2458
2459bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2460 const int32_t* keyCodes, uint8_t* outFlags) {
2461 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
2462}
2463
2464int32_t KeyboardInputMapper::getMetaState() {
2465 return mMetaState;
2466}
2467
Andrii Kulian763a3a42016-03-08 10:46:16 -08002468void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
2469 updateMetaStateIfNeeded(keyCode, false);
2470}
2471
2472bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
2473 int32_t oldMetaState = mMetaState;
2474 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
2475 bool metaStateChanged = oldMetaState != newMetaState;
2476 if (metaStateChanged) {
2477 mMetaState = newMetaState;
2478 updateLedState(false);
2479
2480 getContext()->updateGlobalMetaState();
2481 }
2482
2483 return metaStateChanged;
2484}
2485
Michael Wrightd02c5b62014-02-10 15:10:22 -08002486void KeyboardInputMapper::resetLedState() {
2487 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
2488 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
2489 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
2490
2491 updateLedState(true);
2492}
2493
2494void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
2495 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
2496 ledState.on = false;
2497}
2498
2499void KeyboardInputMapper::updateLedState(bool reset) {
2500 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
2501 AMETA_CAPS_LOCK_ON, reset);
2502 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
2503 AMETA_NUM_LOCK_ON, reset);
2504 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
2505 AMETA_SCROLL_LOCK_ON, reset);
2506}
2507
2508void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
2509 int32_t led, int32_t modifier, bool reset) {
2510 if (ledState.avail) {
2511 bool desiredState = (mMetaState & modifier) != 0;
2512 if (reset || ledState.on != desiredState) {
2513 getEventHub()->setLedState(getDeviceId(), led, desiredState);
2514 ledState.on = desiredState;
2515 }
2516 }
2517}
2518
2519
2520// --- CursorInputMapper ---
2521
2522CursorInputMapper::CursorInputMapper(InputDevice* device) :
2523 InputMapper(device) {
2524}
2525
2526CursorInputMapper::~CursorInputMapper() {
2527}
2528
2529uint32_t CursorInputMapper::getSources() {
2530 return mSource;
2531}
2532
2533void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2534 InputMapper::populateDeviceInfo(info);
2535
2536 if (mParameters.mode == Parameters::MODE_POINTER) {
2537 float minX, minY, maxX, maxY;
2538 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
2539 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
2540 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
2541 }
2542 } else {
2543 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
2544 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
2545 }
2546 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2547
2548 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2549 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2550 }
2551 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2552 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2553 }
2554}
2555
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002556void CursorInputMapper::dump(std::string& dump) {
2557 dump += INDENT2 "Cursor Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002558 dumpParameters(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002559 dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
2560 dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
2561 dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
2562 dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
2563 dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002564 toString(mCursorScrollAccumulator.haveRelativeVWheel()));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002565 dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002566 toString(mCursorScrollAccumulator.haveRelativeHWheel()));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002567 dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
2568 dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
2569 dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
2570 dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
2571 dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
2572 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002573}
2574
2575void CursorInputMapper::configure(nsecs_t when,
2576 const InputReaderConfiguration* config, uint32_t changes) {
2577 InputMapper::configure(when, config, changes);
2578
2579 if (!changes) { // first time only
2580 mCursorScrollAccumulator.configure(getDevice());
2581
2582 // Configure basic parameters.
2583 configureParameters();
2584
2585 // Configure device mode.
2586 switch (mParameters.mode) {
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002587 case Parameters::MODE_POINTER_RELATIVE:
2588 // Should not happen during first time configuration.
2589 ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
2590 mParameters.mode = Parameters::MODE_POINTER;
Chih-Hung Hsieh8d1b40a2018-10-19 11:38:06 -07002591 [[fallthrough]];
Michael Wrightd02c5b62014-02-10 15:10:22 -08002592 case Parameters::MODE_POINTER:
2593 mSource = AINPUT_SOURCE_MOUSE;
2594 mXPrecision = 1.0f;
2595 mYPrecision = 1.0f;
2596 mXScale = 1.0f;
2597 mYScale = 1.0f;
2598 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2599 break;
2600 case Parameters::MODE_NAVIGATION:
2601 mSource = AINPUT_SOURCE_TRACKBALL;
2602 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2603 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2604 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2605 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2606 break;
2607 }
2608
2609 mVWheelScale = 1.0f;
2610 mHWheelScale = 1.0f;
2611 }
2612
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002613 if ((!changes && config->pointerCapture)
2614 || (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
2615 if (config->pointerCapture) {
2616 if (mParameters.mode == Parameters::MODE_POINTER) {
2617 mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
2618 mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
2619 // Keep PointerController around in order to preserve the pointer position.
2620 mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2621 } else {
2622 ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
2623 }
2624 } else {
2625 if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
2626 mParameters.mode = Parameters::MODE_POINTER;
2627 mSource = AINPUT_SOURCE_MOUSE;
2628 } else {
2629 ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
2630 }
2631 }
2632 bumpGeneration();
2633 if (changes) {
2634 getDevice()->notifyReset(when);
2635 }
2636 }
2637
Michael Wrightd02c5b62014-02-10 15:10:22 -08002638 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2639 mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
2640 mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
2641 mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
2642 }
2643
2644 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002645 mOrientation = DISPLAY_ORIENTATION_0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002646 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07002647 std::optional<DisplayViewport> internalViewport =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07002648 config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07002649 if (internalViewport) {
2650 mOrientation = internalViewport->orientation;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002651 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002652 }
Arthur Hungc7ad2d02018-12-18 17:41:29 +08002653
2654 // Update the PointerController if viewports changed.
Arthur Hungc23540e2018-11-29 20:42:11 +08002655 if (mParameters.mode == Parameters::MODE_POINTER) {
Arthur Hungc7ad2d02018-12-18 17:41:29 +08002656 getPolicy()->obtainPointerController(getDeviceId());
2657 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002658 bumpGeneration();
2659 }
2660}
2661
2662void CursorInputMapper::configureParameters() {
2663 mParameters.mode = Parameters::MODE_POINTER;
2664 String8 cursorModeString;
2665 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
2666 if (cursorModeString == "navigation") {
2667 mParameters.mode = Parameters::MODE_NAVIGATION;
2668 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
2669 ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
2670 }
2671 }
2672
2673 mParameters.orientationAware = false;
2674 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
2675 mParameters.orientationAware);
2676
2677 mParameters.hasAssociatedDisplay = false;
2678 if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
2679 mParameters.hasAssociatedDisplay = true;
2680 }
2681}
2682
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002683void CursorInputMapper::dumpParameters(std::string& dump) {
2684 dump += INDENT3 "Parameters:\n";
2685 dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002686 toString(mParameters.hasAssociatedDisplay));
2687
2688 switch (mParameters.mode) {
2689 case Parameters::MODE_POINTER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002690 dump += INDENT4 "Mode: pointer\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002691 break;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002692 case Parameters::MODE_POINTER_RELATIVE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002693 dump += INDENT4 "Mode: relative pointer\n";
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002694 break;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002695 case Parameters::MODE_NAVIGATION:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002696 dump += INDENT4 "Mode: navigation\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002697 break;
2698 default:
2699 ALOG_ASSERT(false);
2700 }
2701
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002702 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002703 toString(mParameters.orientationAware));
2704}
2705
2706void CursorInputMapper::reset(nsecs_t when) {
2707 mButtonState = 0;
2708 mDownTime = 0;
2709
2710 mPointerVelocityControl.reset();
2711 mWheelXVelocityControl.reset();
2712 mWheelYVelocityControl.reset();
2713
2714 mCursorButtonAccumulator.reset(getDevice());
2715 mCursorMotionAccumulator.reset(getDevice());
2716 mCursorScrollAccumulator.reset(getDevice());
2717
2718 InputMapper::reset(when);
2719}
2720
2721void CursorInputMapper::process(const RawEvent* rawEvent) {
2722 mCursorButtonAccumulator.process(rawEvent);
2723 mCursorMotionAccumulator.process(rawEvent);
2724 mCursorScrollAccumulator.process(rawEvent);
2725
2726 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
2727 sync(rawEvent->when);
2728 }
2729}
2730
2731void CursorInputMapper::sync(nsecs_t when) {
2732 int32_t lastButtonState = mButtonState;
2733 int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
2734 mButtonState = currentButtonState;
2735
2736 bool wasDown = isPointerDown(lastButtonState);
2737 bool down = isPointerDown(currentButtonState);
2738 bool downChanged;
2739 if (!wasDown && down) {
2740 mDownTime = when;
2741 downChanged = true;
2742 } else if (wasDown && !down) {
2743 downChanged = true;
2744 } else {
2745 downChanged = false;
2746 }
2747 nsecs_t downTime = mDownTime;
2748 bool buttonsChanged = currentButtonState != lastButtonState;
Michael Wright7b159c92015-05-14 14:48:03 +01002749 int32_t buttonsPressed = currentButtonState & ~lastButtonState;
2750 int32_t buttonsReleased = lastButtonState & ~currentButtonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002751
2752 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
2753 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
2754 bool moved = deltaX != 0 || deltaY != 0;
2755
2756 // Rotate delta according to orientation if needed.
2757 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
2758 && (deltaX != 0.0f || deltaY != 0.0f)) {
2759 rotateDelta(mOrientation, &deltaX, &deltaY);
2760 }
2761
2762 // Move the pointer.
2763 PointerProperties pointerProperties;
2764 pointerProperties.clear();
2765 pointerProperties.id = 0;
2766 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
2767
2768 PointerCoords pointerCoords;
2769 pointerCoords.clear();
2770
2771 float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
2772 float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
2773 bool scrolled = vscroll != 0 || hscroll != 0;
2774
Yi Kong9b14ac62018-07-17 13:48:38 -07002775 mWheelYVelocityControl.move(when, nullptr, &vscroll);
2776 mWheelXVelocityControl.move(when, &hscroll, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002777
2778 mPointerVelocityControl.move(when, &deltaX, &deltaY);
2779
2780 int32_t displayId;
Garfield Tan00f511d2019-06-12 16:55:40 -07002781 float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
2782 float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002783 if (mSource == AINPUT_SOURCE_MOUSE) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002784 if (moved || scrolled || buttonsChanged) {
2785 mPointerController->setPresentation(
2786 PointerControllerInterface::PRESENTATION_POINTER);
2787
2788 if (moved) {
2789 mPointerController->move(deltaX, deltaY);
2790 }
2791
2792 if (buttonsChanged) {
2793 mPointerController->setButtonState(currentButtonState);
2794 }
2795
2796 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2797 }
2798
Garfield Tan00f511d2019-06-12 16:55:40 -07002799 mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
2800 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, xCursorPosition);
2801 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
Jun Mukaifa1706a2015-12-03 01:14:46 -08002802 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
2803 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
Arthur Hungc7ad2d02018-12-18 17:41:29 +08002804 displayId = mPointerController->getDisplayId();
Michael Wrightd02c5b62014-02-10 15:10:22 -08002805 } else {
2806 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
2807 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
2808 displayId = ADISPLAY_ID_NONE;
2809 }
2810
2811 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
2812
2813 // Moving an external trackball or mouse should wake the device.
2814 // We don't do this for internal cursor devices to prevent them from waking up
2815 // the device in your pocket.
2816 // TODO: Use the input device configuration to control this behavior more finely.
2817 uint32_t policyFlags = 0;
2818 if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
Michael Wright872db4f2014-04-22 15:03:51 -07002819 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002820 }
2821
2822 // Synthesize key down from buttons if needed.
2823 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002824 displayId, policyFlags, lastButtonState, currentButtonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002825
2826 // Send motion event.
2827 if (downChanged || moved || scrolled || buttonsChanged) {
2828 int32_t metaState = mContext->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01002829 int32_t buttonState = lastButtonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002830 int32_t motionEventAction;
2831 if (downChanged) {
2832 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002833 } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002834 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2835 } else {
2836 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
2837 }
2838
Michael Wright7b159c92015-05-14 14:48:03 +01002839 if (buttonsReleased) {
2840 BitSet32 released(buttonsReleased);
2841 while (!released.isEmpty()) {
2842 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
2843 buttonState &= ~actionButton;
Prabir Pradhan42611e02018-11-27 14:04:02 -08002844 NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07002845 mSource, displayId, policyFlags,
2846 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
2847 metaState, buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002848 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002849 &pointerCoords, mXPrecision, mYPrecision,
2850 xCursorPosition, yCursorPosition, downTime,
2851 /* videoFrames */ {});
Michael Wright7b159c92015-05-14 14:48:03 +01002852 getListener()->notifyMotion(&releaseArgs);
2853 }
2854 }
2855
Prabir Pradhan42611e02018-11-27 14:04:02 -08002856 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
Garfield Tan00f511d2019-06-12 16:55:40 -07002857 displayId, policyFlags, motionEventAction, 0, 0, metaState,
2858 currentButtonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002859 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
Garfield Tan00f511d2019-06-12 16:55:40 -07002860 mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
2861 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002862 getListener()->notifyMotion(&args);
2863
Michael Wright7b159c92015-05-14 14:48:03 +01002864 if (buttonsPressed) {
2865 BitSet32 pressed(buttonsPressed);
2866 while (!pressed.isEmpty()) {
2867 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
2868 buttonState |= actionButton;
Prabir Pradhan42611e02018-11-27 14:04:02 -08002869 NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07002870 mSource, displayId, policyFlags,
2871 AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
2872 metaState, buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002873 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002874 &pointerCoords, mXPrecision, mYPrecision,
2875 xCursorPosition, yCursorPosition, downTime,
2876 /* videoFrames */ {});
Michael Wright7b159c92015-05-14 14:48:03 +01002877 getListener()->notifyMotion(&pressArgs);
2878 }
2879 }
2880
2881 ALOG_ASSERT(buttonState == currentButtonState);
2882
Michael Wrightd02c5b62014-02-10 15:10:22 -08002883 // Send hover move after UP to tell the application that the mouse is hovering now.
2884 if (motionEventAction == AMOTION_EVENT_ACTION_UP
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002885 && (mSource == AINPUT_SOURCE_MOUSE)) {
Garfield Tan00f511d2019-06-12 16:55:40 -07002886 NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
2887 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
2888 0, metaState, currentButtonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002889 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002890 &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002891 yCursorPosition, downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002892 getListener()->notifyMotion(&hoverArgs);
2893 }
2894
2895 // Send scroll events.
2896 if (scrolled) {
2897 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2898 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2899
Prabir Pradhan42611e02018-11-27 14:04:02 -08002900 NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07002901 mSource, displayId, policyFlags,
2902 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
2903 currentButtonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002904 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
Garfield Tan00f511d2019-06-12 16:55:40 -07002905 &pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07002906 yCursorPosition, downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08002907 getListener()->notifyMotion(&scrollArgs);
2908 }
2909 }
2910
2911 // Synthesize key up from buttons if needed.
2912 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002913 displayId, policyFlags, lastButtonState, currentButtonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002914
2915 mCursorMotionAccumulator.finishSync();
2916 mCursorScrollAccumulator.finishSync();
2917}
2918
2919int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2920 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2921 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2922 } else {
2923 return AKEY_STATE_UNKNOWN;
2924 }
2925}
2926
2927void CursorInputMapper::fadePointer() {
Yi Kong9b14ac62018-07-17 13:48:38 -07002928 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002929 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
2930 }
2931}
2932
Arthur Hungc23540e2018-11-29 20:42:11 +08002933std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
2934 if (mParameters.hasAssociatedDisplay) {
2935 if (mParameters.mode == Parameters::MODE_POINTER) {
2936 return std::make_optional(mPointerController->getDisplayId());
2937 } else {
2938 // If the device is orientationAware and not a mouse,
2939 // it expects to dispatch events to any display
2940 return std::make_optional(ADISPLAY_ID_NONE);
2941 }
2942 }
2943 return std::nullopt;
2944}
2945
Prashant Malani1941ff52015-08-11 18:29:28 -07002946// --- RotaryEncoderInputMapper ---
2947
2948RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
Ivan Podogovad437252016-09-29 16:29:55 +01002949 InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
Prashant Malani1941ff52015-08-11 18:29:28 -07002950 mSource = AINPUT_SOURCE_ROTARY_ENCODER;
2951}
2952
2953RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
2954}
2955
2956uint32_t RotaryEncoderInputMapper::getSources() {
2957 return mSource;
2958}
2959
2960void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2961 InputMapper::populateDeviceInfo(info);
2962
2963 if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
Prashant Malanidae627a2016-01-11 17:08:18 -08002964 float res = 0.0f;
2965 if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
2966 ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
2967 }
2968 if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
2969 mScalingFactor)) {
2970 ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
2971 "default to 1.0!\n");
2972 mScalingFactor = 1.0f;
2973 }
2974 info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
2975 res * mScalingFactor);
Prashant Malani1941ff52015-08-11 18:29:28 -07002976 }
2977}
2978
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002979void RotaryEncoderInputMapper::dump(std::string& dump) {
2980 dump += INDENT2 "Rotary Encoder Input Mapper:\n";
2981 dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
Prashant Malani1941ff52015-08-11 18:29:28 -07002982 toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
2983}
2984
2985void RotaryEncoderInputMapper::configure(nsecs_t when,
2986 const InputReaderConfiguration* config, uint32_t changes) {
2987 InputMapper::configure(when, config, changes);
2988 if (!changes) {
2989 mRotaryEncoderScrollAccumulator.configure(getDevice());
2990 }
Siarhei Vishniakoud00e7872018-08-09 09:22:45 -07002991 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07002992 std::optional<DisplayViewport> internalViewport =
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07002993 config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
Siarhei Vishniakou05a8fe22018-10-03 16:38:28 -07002994 if (internalViewport) {
2995 mOrientation = internalViewport->orientation;
Ivan Podogovad437252016-09-29 16:29:55 +01002996 } else {
2997 mOrientation = DISPLAY_ORIENTATION_0;
2998 }
2999 }
Prashant Malani1941ff52015-08-11 18:29:28 -07003000}
3001
3002void RotaryEncoderInputMapper::reset(nsecs_t when) {
3003 mRotaryEncoderScrollAccumulator.reset(getDevice());
3004
3005 InputMapper::reset(when);
3006}
3007
3008void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
3009 mRotaryEncoderScrollAccumulator.process(rawEvent);
3010
3011 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
3012 sync(rawEvent->when);
3013 }
3014}
3015
3016void RotaryEncoderInputMapper::sync(nsecs_t when) {
3017 PointerCoords pointerCoords;
3018 pointerCoords.clear();
3019
3020 PointerProperties pointerProperties;
3021 pointerProperties.clear();
3022 pointerProperties.id = 0;
3023 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
3024
3025 float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
3026 bool scrolled = scroll != 0;
3027
3028 // This is not a pointer, so it's not associated with a display.
3029 int32_t displayId = ADISPLAY_ID_NONE;
3030
3031 // Moving the rotary encoder should wake the device (if specified).
3032 uint32_t policyFlags = 0;
3033 if (scrolled && getDevice()->isExternal()) {
3034 policyFlags |= POLICY_FLAG_WAKE;
3035 }
3036
Ivan Podogovad437252016-09-29 16:29:55 +01003037 if (mOrientation == DISPLAY_ORIENTATION_180) {
3038 scroll = -scroll;
3039 }
3040
Prashant Malani1941ff52015-08-11 18:29:28 -07003041 // Send motion event.
3042 if (scrolled) {
3043 int32_t metaState = mContext->getGlobalMetaState();
Prashant Malanidae627a2016-01-11 17:08:18 -08003044 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
Prashant Malani1941ff52015-08-11 18:29:28 -07003045
Garfield Tan00f511d2019-06-12 16:55:40 -07003046 NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
3047 displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
3048 metaState, /* buttonState */ 0, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07003049 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
3050 &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Garfield Tan00f511d2019-06-12 16:55:40 -07003051 AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
Prashant Malani1941ff52015-08-11 18:29:28 -07003052 getListener()->notifyMotion(&scrollArgs);
3053 }
3054
3055 mRotaryEncoderScrollAccumulator.finishSync();
3056}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003057
3058// --- TouchInputMapper ---
3059
3060TouchInputMapper::TouchInputMapper(InputDevice* device) :
3061 InputMapper(device),
3062 mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
3063 mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
Michael Wright358bcc72018-08-21 04:01:07 +01003064 mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003065 mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
3066}
3067
3068TouchInputMapper::~TouchInputMapper() {
3069}
3070
3071uint32_t TouchInputMapper::getSources() {
3072 return mSource;
3073}
3074
3075void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3076 InputMapper::populateDeviceInfo(info);
3077
3078 if (mDeviceMode != DEVICE_MODE_DISABLED) {
3079 info->addMotionRange(mOrientedRanges.x);
3080 info->addMotionRange(mOrientedRanges.y);
3081 info->addMotionRange(mOrientedRanges.pressure);
3082
3083 if (mOrientedRanges.haveSize) {
3084 info->addMotionRange(mOrientedRanges.size);
3085 }
3086
3087 if (mOrientedRanges.haveTouchSize) {
3088 info->addMotionRange(mOrientedRanges.touchMajor);
3089 info->addMotionRange(mOrientedRanges.touchMinor);
3090 }
3091
3092 if (mOrientedRanges.haveToolSize) {
3093 info->addMotionRange(mOrientedRanges.toolMajor);
3094 info->addMotionRange(mOrientedRanges.toolMinor);
3095 }
3096
3097 if (mOrientedRanges.haveOrientation) {
3098 info->addMotionRange(mOrientedRanges.orientation);
3099 }
3100
3101 if (mOrientedRanges.haveDistance) {
3102 info->addMotionRange(mOrientedRanges.distance);
3103 }
3104
3105 if (mOrientedRanges.haveTilt) {
3106 info->addMotionRange(mOrientedRanges.tilt);
3107 }
3108
3109 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
3110 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3111 0.0f);
3112 }
3113 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
3114 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3115 0.0f);
3116 }
3117 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
3118 const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
3119 const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
3120 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
3121 x.fuzz, x.resolution);
3122 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
3123 y.fuzz, y.resolution);
3124 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
3125 x.fuzz, x.resolution);
3126 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
3127 y.fuzz, y.resolution);
3128 }
3129 info->setButtonUnderPad(mParameters.hasButtonUnderPad);
3130 }
3131}
3132
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003133void TouchInputMapper::dump(std::string& dump) {
3134 dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003135 dumpParameters(dump);
3136 dumpVirtualKeys(dump);
3137 dumpRawPointerAxes(dump);
3138 dumpCalibration(dump);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07003139 dumpAffineTransformation(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003140 dumpSurface(dump);
3141
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003142 dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
3143 dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
3144 dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
3145 dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
3146 dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
3147 dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
3148 dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
3149 dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
3150 dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
3151 dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
3152 dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
3153 dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
3154 dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
3155 dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
3156 dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
3157 dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
3158 dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003159
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003160 dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
3161 dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07003162 mLastRawState.rawPointerData.pointerCount);
3163 for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
3164 const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003165 dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003166 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
3167 "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
3168 "toolType=%d, isHovering=%s\n", i,
3169 pointer.id, pointer.x, pointer.y, pointer.pressure,
3170 pointer.touchMajor, pointer.touchMinor,
3171 pointer.toolMajor, pointer.toolMinor,
3172 pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
3173 pointer.toolType, toString(pointer.isHovering));
3174 }
3175
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003176 dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState);
3177 dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07003178 mLastCookedState.cookedPointerData.pointerCount);
3179 for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
3180 const PointerProperties& pointerProperties =
3181 mLastCookedState.cookedPointerData.pointerProperties[i];
3182 const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003183 dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003184 "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
3185 "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
3186 "toolType=%d, isHovering=%s\n", i,
3187 pointerProperties.id,
3188 pointerCoords.getX(),
3189 pointerCoords.getY(),
3190 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
3191 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
3192 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
3193 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
3194 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
3195 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
3196 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
3197 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
3198 pointerProperties.toolType,
Michael Wright842500e2015-03-13 17:32:02 -07003199 toString(mLastCookedState.cookedPointerData.isHovering(i)));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003200 }
3201
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003202 dump += INDENT3 "Stylus Fusion:\n";
3203 dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
Michael Wright842500e2015-03-13 17:32:02 -07003204 toString(mExternalStylusConnected));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003205 dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
3206 dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
Michael Wright43fd19f2015-04-21 19:02:58 +01003207 mExternalStylusFusionTimeout);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003208 dump += INDENT3 "External Stylus State:\n";
Michael Wright842500e2015-03-13 17:32:02 -07003209 dumpStylusState(dump, mExternalStylusState);
3210
Michael Wrightd02c5b62014-02-10 15:10:22 -08003211 if (mDeviceMode == DEVICE_MODE_POINTER) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003212 dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
3213 dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003214 mPointerXMovementScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003215 dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003216 mPointerYMovementScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003217 dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003218 mPointerXZoomScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003219 dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003220 mPointerYZoomScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003221 dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003222 mPointerGestureMaxSwipeWidth);
3223 }
3224}
3225
Santos Cordonfa5cf462017-04-05 10:37:00 -07003226const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
3227 switch (deviceMode) {
3228 case DEVICE_MODE_DISABLED:
3229 return "disabled";
3230 case DEVICE_MODE_DIRECT:
3231 return "direct";
3232 case DEVICE_MODE_UNSCALED:
3233 return "unscaled";
3234 case DEVICE_MODE_NAVIGATION:
3235 return "navigation";
3236 case DEVICE_MODE_POINTER:
3237 return "pointer";
3238 }
3239 return "unknown";
3240}
3241
Michael Wrightd02c5b62014-02-10 15:10:22 -08003242void TouchInputMapper::configure(nsecs_t when,
3243 const InputReaderConfiguration* config, uint32_t changes) {
3244 InputMapper::configure(when, config, changes);
3245
3246 mConfig = *config;
3247
3248 if (!changes) { // first time only
3249 // Configure basic parameters.
3250 configureParameters();
3251
3252 // Configure common accumulators.
3253 mCursorScrollAccumulator.configure(getDevice());
3254 mTouchButtonAccumulator.configure(getDevice());
3255
3256 // Configure absolute axis information.
3257 configureRawPointerAxes();
3258
3259 // Prepare input device calibration.
3260 parseCalibration();
3261 resolveCalibration();
3262 }
3263
Michael Wright842500e2015-03-13 17:32:02 -07003264 if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
Jason Gerecke12d6baa2014-01-27 18:34:20 -08003265 // Update location calibration to reflect current settings
3266 updateAffineTransformation();
3267 }
3268
Michael Wrightd02c5b62014-02-10 15:10:22 -08003269 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
3270 // Update pointer speed.
3271 mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
3272 mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
3273 mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
3274 }
3275
3276 bool resetNeeded = false;
3277 if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
3278 | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
Michael Wright842500e2015-03-13 17:32:02 -07003279 | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
3280 | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003281 // Configure device sources, surface dimensions, orientation and
3282 // scaling factors.
3283 configureSurface(when, &resetNeeded);
3284 }
3285
3286 if (changes && resetNeeded) {
3287 // Send reset, unless this is the first time the device has been configured,
3288 // in which case the reader will call reset itself after all mappers are ready.
3289 getDevice()->notifyReset(when);
3290 }
3291}
3292
Michael Wright842500e2015-03-13 17:32:02 -07003293void TouchInputMapper::resolveExternalStylusPresence() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003294 std::vector<InputDeviceInfo> devices;
Michael Wright842500e2015-03-13 17:32:02 -07003295 mContext->getExternalStylusDevices(devices);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003296 mExternalStylusConnected = !devices.empty();
Michael Wright842500e2015-03-13 17:32:02 -07003297
3298 if (!mExternalStylusConnected) {
3299 resetExternalStylus();
3300 }
3301}
3302
Michael Wrightd02c5b62014-02-10 15:10:22 -08003303void TouchInputMapper::configureParameters() {
3304 // Use the pointer presentation mode for devices that do not support distinct
3305 // multitouch. The spot-based presentation relies on being able to accurately
3306 // locate two or more fingers on the touch pad.
3307 mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003308 ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003309
3310 String8 gestureModeString;
3311 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
3312 gestureModeString)) {
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003313 if (gestureModeString == "single-touch") {
3314 mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
3315 } else if (gestureModeString == "multi-touch") {
3316 mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003317 } else if (gestureModeString != "default") {
3318 ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
3319 }
3320 }
3321
3322 if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
3323 // The device is a touch screen.
3324 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3325 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
3326 // The device is a pointing device like a track pad.
3327 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3328 } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
3329 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
3330 // The device is a cursor device with a touch pad attached.
3331 // By default don't use the touch pad to move the pointer.
3332 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
3333 } else {
3334 // The device is a touch pad of unknown purpose.
3335 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3336 }
3337
3338 mParameters.hasButtonUnderPad=
3339 getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
3340
3341 String8 deviceTypeString;
3342 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
3343 deviceTypeString)) {
3344 if (deviceTypeString == "touchScreen") {
3345 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3346 } else if (deviceTypeString == "touchPad") {
3347 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
3348 } else if (deviceTypeString == "touchNavigation") {
3349 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
3350 } else if (deviceTypeString == "pointer") {
3351 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3352 } else if (deviceTypeString != "default") {
3353 ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
3354 }
3355 }
3356
3357 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3358 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
3359 mParameters.orientationAware);
3360
3361 mParameters.hasAssociatedDisplay = false;
3362 mParameters.associatedDisplayIsExternal = false;
3363 if (mParameters.orientationAware
3364 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3365 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
3366 mParameters.hasAssociatedDisplay = true;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003367 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
3368 mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003369 String8 uniqueDisplayId;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003370 getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003371 uniqueDisplayId);
3372 mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
Santos Cordonfa5cf462017-04-05 10:37:00 -07003373 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003374 }
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003375 if (getDevice()->getAssociatedDisplayPort()) {
3376 mParameters.hasAssociatedDisplay = true;
3377 }
Jeff Brownc5e24422014-02-26 18:48:51 -08003378
3379 // Initial downs on external touch devices should wake the device.
3380 // Normally we don't do this for internal touch screens to prevent them from waking
3381 // up in your pocket but you can enable it using the input device configuration.
3382 mParameters.wake = getDevice()->isExternal();
3383 getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"),
3384 mParameters.wake);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003385}
3386
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003387void TouchInputMapper::dumpParameters(std::string& dump) {
3388 dump += INDENT3 "Parameters:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003389
3390 switch (mParameters.gestureMode) {
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003391 case Parameters::GESTURE_MODE_SINGLE_TOUCH:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003392 dump += INDENT4 "GestureMode: single-touch\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003393 break;
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003394 case Parameters::GESTURE_MODE_MULTI_TOUCH:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003395 dump += INDENT4 "GestureMode: multi-touch\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003396 break;
3397 default:
3398 assert(false);
3399 }
3400
3401 switch (mParameters.deviceType) {
3402 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003403 dump += INDENT4 "DeviceType: touchScreen\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003404 break;
3405 case Parameters::DEVICE_TYPE_TOUCH_PAD:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003406 dump += INDENT4 "DeviceType: touchPad\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003407 break;
3408 case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003409 dump += INDENT4 "DeviceType: touchNavigation\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003410 break;
3411 case Parameters::DEVICE_TYPE_POINTER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003412 dump += INDENT4 "DeviceType: pointer\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003413 break;
3414 default:
3415 ALOG_ASSERT(false);
3416 }
3417
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003418 dump += StringPrintf(
Santos Cordonfa5cf462017-04-05 10:37:00 -07003419 INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, displayId='%s'\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003420 toString(mParameters.hasAssociatedDisplay),
Santos Cordonfa5cf462017-04-05 10:37:00 -07003421 toString(mParameters.associatedDisplayIsExternal),
3422 mParameters.uniqueDisplayId.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003423 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003424 toString(mParameters.orientationAware));
3425}
3426
3427void TouchInputMapper::configureRawPointerAxes() {
3428 mRawPointerAxes.clear();
3429}
3430
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003431void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
3432 dump += INDENT3 "Raw Touch Axes:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003433 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
3434 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
3435 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
3436 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
3437 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
3438 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
3439 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
3440 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
3441 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
3442 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
3443 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
3444 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
3445 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
3446}
3447
Michael Wright842500e2015-03-13 17:32:02 -07003448bool TouchInputMapper::hasExternalStylus() const {
3449 return mExternalStylusConnected;
3450}
3451
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003452/**
3453 * Determine which DisplayViewport to use.
3454 * 1. If display port is specified, return the matching viewport. If matching viewport not
3455 * found, then return.
3456 * 2. If a device has associated display, get the matching viewport by either unique id or by
3457 * the display type (internal or external).
3458 * 3. Otherwise, use a non-display viewport.
3459 */
3460std::optional<DisplayViewport> TouchInputMapper::findViewport() {
3461 if (mParameters.hasAssociatedDisplay) {
3462 const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
3463 if (displayPort) {
3464 // Find the viewport that contains the same port
3465 std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
3466 if (!v) {
3467 ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
3468 "but the corresponding viewport is not found.",
3469 getDeviceName().c_str(), *displayPort);
3470 }
3471 return v;
3472 }
3473
3474 if (!mParameters.uniqueDisplayId.empty()) {
3475 return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
3476 }
3477
3478 ViewportType viewportTypeToUse;
3479 if (mParameters.associatedDisplayIsExternal) {
3480 viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
3481 } else {
3482 viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
3483 }
Arthur Hung41a712e2018-11-22 19:41:03 +08003484
3485 std::optional<DisplayViewport> viewport =
3486 mConfig.getDisplayViewportByType(viewportTypeToUse);
3487 if (!viewport && viewportTypeToUse == ViewportType::VIEWPORT_EXTERNAL) {
3488 ALOGW("Input device %s should be associated with external display, "
3489 "fallback to internal one for the external viewport is not found.",
3490 getDeviceName().c_str());
3491 viewport = mConfig.getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
3492 }
3493
3494 return viewport;
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003495 }
3496
3497 DisplayViewport newViewport;
3498 // Raw width and height in the natural orientation.
3499 int32_t rawWidth = mRawPointerAxes.getRawWidth();
3500 int32_t rawHeight = mRawPointerAxes.getRawHeight();
3501 newViewport.setNonDisplayViewport(rawWidth, rawHeight);
3502 return std::make_optional(newViewport);
3503}
3504
Michael Wrightd02c5b62014-02-10 15:10:22 -08003505void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
3506 int32_t oldDeviceMode = mDeviceMode;
3507
Michael Wright842500e2015-03-13 17:32:02 -07003508 resolveExternalStylusPresence();
3509
Michael Wrightd02c5b62014-02-10 15:10:22 -08003510 // Determine device mode.
3511 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
3512 && mConfig.pointerGesturesEnabled) {
3513 mSource = AINPUT_SOURCE_MOUSE;
3514 mDeviceMode = DEVICE_MODE_POINTER;
3515 if (hasStylus()) {
3516 mSource |= AINPUT_SOURCE_STYLUS;
3517 }
3518 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3519 && mParameters.hasAssociatedDisplay) {
3520 mSource = AINPUT_SOURCE_TOUCHSCREEN;
3521 mDeviceMode = DEVICE_MODE_DIRECT;
Michael Wright2f78b682015-06-12 15:25:08 +01003522 if (hasStylus()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003523 mSource |= AINPUT_SOURCE_STYLUS;
3524 }
Michael Wright2f78b682015-06-12 15:25:08 +01003525 if (hasExternalStylus()) {
3526 mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
3527 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003528 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
3529 mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
3530 mDeviceMode = DEVICE_MODE_NAVIGATION;
3531 } else {
3532 mSource = AINPUT_SOURCE_TOUCHPAD;
3533 mDeviceMode = DEVICE_MODE_UNSCALED;
3534 }
3535
3536 // Ensure we have valid X and Y axes.
3537 if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003538 ALOGW("Touch device '%s' did not report support for X or Y axis! "
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003539 "The device will be inoperable.", getDeviceName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003540 mDeviceMode = DEVICE_MODE_DISABLED;
3541 return;
3542 }
3543
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003544 // Get associated display dimensions.
3545 std::optional<DisplayViewport> newViewport = findViewport();
3546 if (!newViewport) {
3547 ALOGI("Touch device '%s' could not query the properties of its associated "
3548 "display. The device will be inoperable until the display size "
3549 "becomes available.",
3550 getDeviceName().c_str());
3551 mDeviceMode = DEVICE_MODE_DISABLED;
3552 return;
3553 }
3554
Michael Wrightd02c5b62014-02-10 15:10:22 -08003555 // Raw width and height in the natural orientation.
Siarhei Vishniakou26e34d92018-11-12 13:51:26 -08003556 int32_t rawWidth = mRawPointerAxes.getRawWidth();
3557 int32_t rawHeight = mRawPointerAxes.getRawHeight();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003558
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003559 bool viewportChanged = mViewport != *newViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003560 if (viewportChanged) {
Siarhei Vishniakou8158e7e2018-10-15 14:28:20 -07003561 mViewport = *newViewport;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003562
3563 if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
3564 // Convert rotated viewport to natural surface coordinates.
3565 int32_t naturalLogicalWidth, naturalLogicalHeight;
3566 int32_t naturalPhysicalWidth, naturalPhysicalHeight;
3567 int32_t naturalPhysicalLeft, naturalPhysicalTop;
3568 int32_t naturalDeviceWidth, naturalDeviceHeight;
3569 switch (mViewport.orientation) {
3570 case DISPLAY_ORIENTATION_90:
3571 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3572 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3573 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3574 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3575 naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
3576 naturalPhysicalTop = mViewport.physicalLeft;
3577 naturalDeviceWidth = mViewport.deviceHeight;
3578 naturalDeviceHeight = mViewport.deviceWidth;
3579 break;
3580 case DISPLAY_ORIENTATION_180:
3581 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3582 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3583 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3584 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3585 naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
3586 naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
3587 naturalDeviceWidth = mViewport.deviceWidth;
3588 naturalDeviceHeight = mViewport.deviceHeight;
3589 break;
3590 case DISPLAY_ORIENTATION_270:
3591 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3592 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3593 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3594 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3595 naturalPhysicalLeft = mViewport.physicalTop;
3596 naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
3597 naturalDeviceWidth = mViewport.deviceHeight;
3598 naturalDeviceHeight = mViewport.deviceWidth;
3599 break;
3600 case DISPLAY_ORIENTATION_0:
3601 default:
3602 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3603 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3604 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3605 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3606 naturalPhysicalLeft = mViewport.physicalLeft;
3607 naturalPhysicalTop = mViewport.physicalTop;
3608 naturalDeviceWidth = mViewport.deviceWidth;
3609 naturalDeviceHeight = mViewport.deviceHeight;
3610 break;
3611 }
3612
Siarhei Vishniakoud6343922018-07-06 23:33:37 +01003613 if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
3614 ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
3615 naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
3616 naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
3617 }
3618
Michael Wright358bcc72018-08-21 04:01:07 +01003619 mPhysicalWidth = naturalPhysicalWidth;
3620 mPhysicalHeight = naturalPhysicalHeight;
3621 mPhysicalLeft = naturalPhysicalLeft;
3622 mPhysicalTop = naturalPhysicalTop;
3623
Michael Wrightd02c5b62014-02-10 15:10:22 -08003624 mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
3625 mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
3626 mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
3627 mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
3628
3629 mSurfaceOrientation = mParameters.orientationAware ?
3630 mViewport.orientation : DISPLAY_ORIENTATION_0;
3631 } else {
Michael Wright358bcc72018-08-21 04:01:07 +01003632 mPhysicalWidth = rawWidth;
3633 mPhysicalHeight = rawHeight;
3634 mPhysicalLeft = 0;
3635 mPhysicalTop = 0;
3636
Michael Wrightd02c5b62014-02-10 15:10:22 -08003637 mSurfaceWidth = rawWidth;
3638 mSurfaceHeight = rawHeight;
3639 mSurfaceLeft = 0;
3640 mSurfaceTop = 0;
3641 mSurfaceOrientation = DISPLAY_ORIENTATION_0;
3642 }
3643 }
3644
3645 // If moving between pointer modes, need to reset some state.
3646 bool deviceModeChanged = mDeviceMode != oldDeviceMode;
3647 if (deviceModeChanged) {
3648 mOrientedRanges.clear();
3649 }
3650
Arthur Hungc7ad2d02018-12-18 17:41:29 +08003651 // Create or update pointer controller if needed.
Michael Wrightd02c5b62014-02-10 15:10:22 -08003652 if (mDeviceMode == DEVICE_MODE_POINTER ||
3653 (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
Arthur Hungc7ad2d02018-12-18 17:41:29 +08003654 if (mPointerController == nullptr || viewportChanged) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003655 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
3656 }
3657 } else {
3658 mPointerController.clear();
3659 }
3660
3661 if (viewportChanged || deviceModeChanged) {
3662 ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
3663 "display id %d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003664 getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
Michael Wrightd02c5b62014-02-10 15:10:22 -08003665 mSurfaceOrientation, mDeviceMode, mViewport.displayId);
3666
3667 // Configure X and Y factors.
3668 mXScale = float(mSurfaceWidth) / rawWidth;
3669 mYScale = float(mSurfaceHeight) / rawHeight;
3670 mXTranslate = -mSurfaceLeft;
3671 mYTranslate = -mSurfaceTop;
3672 mXPrecision = 1.0f / mXScale;
3673 mYPrecision = 1.0f / mYScale;
3674
3675 mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
3676 mOrientedRanges.x.source = mSource;
3677 mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
3678 mOrientedRanges.y.source = mSource;
3679
3680 configureVirtualKeys();
3681
3682 // Scale factor for terms that are not oriented in a particular axis.
3683 // If the pixels are square then xScale == yScale otherwise we fake it
3684 // by choosing an average.
3685 mGeometricScale = avg(mXScale, mYScale);
3686
3687 // Size of diagonal axis.
3688 float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
3689
3690 // Size factors.
3691 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
3692 if (mRawPointerAxes.touchMajor.valid
3693 && mRawPointerAxes.touchMajor.maxValue != 0) {
3694 mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
3695 } else if (mRawPointerAxes.toolMajor.valid
3696 && mRawPointerAxes.toolMajor.maxValue != 0) {
3697 mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
3698 } else {
3699 mSizeScale = 0.0f;
3700 }
3701
3702 mOrientedRanges.haveTouchSize = true;
3703 mOrientedRanges.haveToolSize = true;
3704 mOrientedRanges.haveSize = true;
3705
3706 mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
3707 mOrientedRanges.touchMajor.source = mSource;
3708 mOrientedRanges.touchMajor.min = 0;
3709 mOrientedRanges.touchMajor.max = diagonalSize;
3710 mOrientedRanges.touchMajor.flat = 0;
3711 mOrientedRanges.touchMajor.fuzz = 0;
3712 mOrientedRanges.touchMajor.resolution = 0;
3713
3714 mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
3715 mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
3716
3717 mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
3718 mOrientedRanges.toolMajor.source = mSource;
3719 mOrientedRanges.toolMajor.min = 0;
3720 mOrientedRanges.toolMajor.max = diagonalSize;
3721 mOrientedRanges.toolMajor.flat = 0;
3722 mOrientedRanges.toolMajor.fuzz = 0;
3723 mOrientedRanges.toolMajor.resolution = 0;
3724
3725 mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
3726 mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
3727
3728 mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
3729 mOrientedRanges.size.source = mSource;
3730 mOrientedRanges.size.min = 0;
3731 mOrientedRanges.size.max = 1.0;
3732 mOrientedRanges.size.flat = 0;
3733 mOrientedRanges.size.fuzz = 0;
3734 mOrientedRanges.size.resolution = 0;
3735 } else {
3736 mSizeScale = 0.0f;
3737 }
3738
3739 // Pressure factors.
3740 mPressureScale = 0;
Michael Wrightaa449c92017-12-13 21:21:43 +00003741 float pressureMax = 1.0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003742 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
3743 || mCalibration.pressureCalibration
3744 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
3745 if (mCalibration.havePressureScale) {
3746 mPressureScale = mCalibration.pressureScale;
Michael Wrightaa449c92017-12-13 21:21:43 +00003747 pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003748 } else if (mRawPointerAxes.pressure.valid
3749 && mRawPointerAxes.pressure.maxValue != 0) {
3750 mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
3751 }
3752 }
3753
3754 mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
3755 mOrientedRanges.pressure.source = mSource;
3756 mOrientedRanges.pressure.min = 0;
Michael Wrightaa449c92017-12-13 21:21:43 +00003757 mOrientedRanges.pressure.max = pressureMax;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003758 mOrientedRanges.pressure.flat = 0;
3759 mOrientedRanges.pressure.fuzz = 0;
3760 mOrientedRanges.pressure.resolution = 0;
3761
3762 // Tilt
3763 mTiltXCenter = 0;
3764 mTiltXScale = 0;
3765 mTiltYCenter = 0;
3766 mTiltYScale = 0;
3767 mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
3768 if (mHaveTilt) {
3769 mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
3770 mRawPointerAxes.tiltX.maxValue);
3771 mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
3772 mRawPointerAxes.tiltY.maxValue);
3773 mTiltXScale = M_PI / 180;
3774 mTiltYScale = M_PI / 180;
3775
3776 mOrientedRanges.haveTilt = true;
3777
3778 mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
3779 mOrientedRanges.tilt.source = mSource;
3780 mOrientedRanges.tilt.min = 0;
3781 mOrientedRanges.tilt.max = M_PI_2;
3782 mOrientedRanges.tilt.flat = 0;
3783 mOrientedRanges.tilt.fuzz = 0;
3784 mOrientedRanges.tilt.resolution = 0;
3785 }
3786
3787 // Orientation
3788 mOrientationScale = 0;
3789 if (mHaveTilt) {
3790 mOrientedRanges.haveOrientation = true;
3791
3792 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3793 mOrientedRanges.orientation.source = mSource;
3794 mOrientedRanges.orientation.min = -M_PI;
3795 mOrientedRanges.orientation.max = M_PI;
3796 mOrientedRanges.orientation.flat = 0;
3797 mOrientedRanges.orientation.fuzz = 0;
3798 mOrientedRanges.orientation.resolution = 0;
3799 } else if (mCalibration.orientationCalibration !=
3800 Calibration::ORIENTATION_CALIBRATION_NONE) {
3801 if (mCalibration.orientationCalibration
3802 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
3803 if (mRawPointerAxes.orientation.valid) {
3804 if (mRawPointerAxes.orientation.maxValue > 0) {
3805 mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
3806 } else if (mRawPointerAxes.orientation.minValue < 0) {
3807 mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
3808 } else {
3809 mOrientationScale = 0;
3810 }
3811 }
3812 }
3813
3814 mOrientedRanges.haveOrientation = true;
3815
3816 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3817 mOrientedRanges.orientation.source = mSource;
3818 mOrientedRanges.orientation.min = -M_PI_2;
3819 mOrientedRanges.orientation.max = M_PI_2;
3820 mOrientedRanges.orientation.flat = 0;
3821 mOrientedRanges.orientation.fuzz = 0;
3822 mOrientedRanges.orientation.resolution = 0;
3823 }
3824
3825 // Distance
3826 mDistanceScale = 0;
3827 if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
3828 if (mCalibration.distanceCalibration
3829 == Calibration::DISTANCE_CALIBRATION_SCALED) {
3830 if (mCalibration.haveDistanceScale) {
3831 mDistanceScale = mCalibration.distanceScale;
3832 } else {
3833 mDistanceScale = 1.0f;
3834 }
3835 }
3836
3837 mOrientedRanges.haveDistance = true;
3838
3839 mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
3840 mOrientedRanges.distance.source = mSource;
3841 mOrientedRanges.distance.min =
3842 mRawPointerAxes.distance.minValue * mDistanceScale;
3843 mOrientedRanges.distance.max =
3844 mRawPointerAxes.distance.maxValue * mDistanceScale;
3845 mOrientedRanges.distance.flat = 0;
3846 mOrientedRanges.distance.fuzz =
3847 mRawPointerAxes.distance.fuzz * mDistanceScale;
3848 mOrientedRanges.distance.resolution = 0;
3849 }
3850
3851 // Compute oriented precision, scales and ranges.
3852 // Note that the maximum value reported is an inclusive maximum value so it is one
3853 // unit less than the total width or height of surface.
3854 switch (mSurfaceOrientation) {
3855 case DISPLAY_ORIENTATION_90:
3856 case DISPLAY_ORIENTATION_270:
3857 mOrientedXPrecision = mYPrecision;
3858 mOrientedYPrecision = mXPrecision;
3859
3860 mOrientedRanges.x.min = mYTranslate;
3861 mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
3862 mOrientedRanges.x.flat = 0;
3863 mOrientedRanges.x.fuzz = 0;
3864 mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
3865
3866 mOrientedRanges.y.min = mXTranslate;
3867 mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
3868 mOrientedRanges.y.flat = 0;
3869 mOrientedRanges.y.fuzz = 0;
3870 mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
3871 break;
3872
3873 default:
3874 mOrientedXPrecision = mXPrecision;
3875 mOrientedYPrecision = mYPrecision;
3876
3877 mOrientedRanges.x.min = mXTranslate;
3878 mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
3879 mOrientedRanges.x.flat = 0;
3880 mOrientedRanges.x.fuzz = 0;
3881 mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
3882
3883 mOrientedRanges.y.min = mYTranslate;
3884 mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
3885 mOrientedRanges.y.flat = 0;
3886 mOrientedRanges.y.fuzz = 0;
3887 mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
3888 break;
3889 }
3890
Jason Gerecke71b16e82014-03-10 09:47:59 -07003891 // Location
3892 updateAffineTransformation();
3893
Michael Wrightd02c5b62014-02-10 15:10:22 -08003894 if (mDeviceMode == DEVICE_MODE_POINTER) {
3895 // Compute pointer gesture detection parameters.
3896 float rawDiagonal = hypotf(rawWidth, rawHeight);
3897 float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
3898
3899 // Scale movements such that one whole swipe of the touch pad covers a
3900 // given area relative to the diagonal size of the display when no acceleration
3901 // is applied.
3902 // Assume that the touch pad has a square aspect ratio such that movements in
3903 // X and Y of the same number of raw units cover the same physical distance.
3904 mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
3905 * displayDiagonal / rawDiagonal;
3906 mPointerYMovementScale = mPointerXMovementScale;
3907
3908 // Scale zooms to cover a smaller range of the display than movements do.
3909 // This value determines the area around the pointer that is affected by freeform
3910 // pointer gestures.
3911 mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
3912 * displayDiagonal / rawDiagonal;
3913 mPointerYZoomScale = mPointerXZoomScale;
3914
3915 // Max width between pointers to detect a swipe gesture is more than some fraction
3916 // of the diagonal axis of the touch pad. Touches that are wider than this are
3917 // translated into freeform gestures.
3918 mPointerGestureMaxSwipeWidth =
3919 mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
3920
3921 // Abort current pointer usages because the state has changed.
3922 abortPointerUsage(when, 0 /*policyFlags*/);
3923 }
3924
3925 // Inform the dispatcher about the changes.
3926 *outResetNeeded = true;
3927 bumpGeneration();
3928 }
3929}
3930
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003931void TouchInputMapper::dumpSurface(std::string& dump) {
Siarhei Vishniakoud6343922018-07-06 23:33:37 +01003932 dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003933 dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
3934 dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
3935 dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
3936 dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
Michael Wright358bcc72018-08-21 04:01:07 +01003937 dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
3938 dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
3939 dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
3940 dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003941 dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003942}
3943
3944void TouchInputMapper::configureVirtualKeys() {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003945 std::vector<VirtualKeyDefinition> virtualKeyDefinitions;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003946 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
3947
3948 mVirtualKeys.clear();
3949
3950 if (virtualKeyDefinitions.size() == 0) {
3951 return;
3952 }
3953
Michael Wrightd02c5b62014-02-10 15:10:22 -08003954 int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
3955 int32_t touchScreenTop = mRawPointerAxes.y.minValue;
Siarhei Vishniakou26e34d92018-11-12 13:51:26 -08003956 int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
3957 int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003958
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003959 for (const VirtualKeyDefinition& virtualKeyDefinition : virtualKeyDefinitions) {
3960 VirtualKey virtualKey;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003961
3962 virtualKey.scanCode = virtualKeyDefinition.scanCode;
3963 int32_t keyCode;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07003964 int32_t dummyKeyMetaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003965 uint32_t flags;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07003966 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0,
3967 &keyCode, &dummyKeyMetaState, &flags)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003968 ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
3969 virtualKey.scanCode);
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003970 continue; // drop the key
Michael Wrightd02c5b62014-02-10 15:10:22 -08003971 }
3972
3973 virtualKey.keyCode = keyCode;
3974 virtualKey.flags = flags;
3975
3976 // convert the key definition's display coordinates into touch coordinates for a hit box
3977 int32_t halfWidth = virtualKeyDefinition.width / 2;
3978 int32_t halfHeight = virtualKeyDefinition.height / 2;
3979
3980 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
3981 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3982 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
3983 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3984 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
3985 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3986 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
3987 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003988 mVirtualKeys.push_back(virtualKey);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003989 }
3990}
3991
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003992void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003993 if (!mVirtualKeys.empty()) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003994 dump += INDENT3 "Virtual Keys:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003995
3996 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08003997 const VirtualKey& virtualKey = mVirtualKeys[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003998 dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003999 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
4000 i, virtualKey.scanCode, virtualKey.keyCode,
4001 virtualKey.hitLeft, virtualKey.hitRight,
4002 virtualKey.hitTop, virtualKey.hitBottom);
4003 }
4004 }
4005}
4006
4007void TouchInputMapper::parseCalibration() {
4008 const PropertyMap& in = getDevice()->getConfiguration();
4009 Calibration& out = mCalibration;
4010
4011 // Size
4012 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
4013 String8 sizeCalibrationString;
4014 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
4015 if (sizeCalibrationString == "none") {
4016 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
4017 } else if (sizeCalibrationString == "geometric") {
4018 out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
4019 } else if (sizeCalibrationString == "diameter") {
4020 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
4021 } else if (sizeCalibrationString == "box") {
4022 out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
4023 } else if (sizeCalibrationString == "area") {
4024 out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
4025 } else if (sizeCalibrationString != "default") {
4026 ALOGW("Invalid value for touch.size.calibration: '%s'",
4027 sizeCalibrationString.string());
4028 }
4029 }
4030
4031 out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
4032 out.sizeScale);
4033 out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
4034 out.sizeBias);
4035 out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
4036 out.sizeIsSummed);
4037
4038 // Pressure
4039 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
4040 String8 pressureCalibrationString;
4041 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
4042 if (pressureCalibrationString == "none") {
4043 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
4044 } else if (pressureCalibrationString == "physical") {
4045 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
4046 } else if (pressureCalibrationString == "amplitude") {
4047 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
4048 } else if (pressureCalibrationString != "default") {
4049 ALOGW("Invalid value for touch.pressure.calibration: '%s'",
4050 pressureCalibrationString.string());
4051 }
4052 }
4053
4054 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
4055 out.pressureScale);
4056
4057 // Orientation
4058 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
4059 String8 orientationCalibrationString;
4060 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
4061 if (orientationCalibrationString == "none") {
4062 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
4063 } else if (orientationCalibrationString == "interpolated") {
4064 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
4065 } else if (orientationCalibrationString == "vector") {
4066 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
4067 } else if (orientationCalibrationString != "default") {
4068 ALOGW("Invalid value for touch.orientation.calibration: '%s'",
4069 orientationCalibrationString.string());
4070 }
4071 }
4072
4073 // Distance
4074 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
4075 String8 distanceCalibrationString;
4076 if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
4077 if (distanceCalibrationString == "none") {
4078 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
4079 } else if (distanceCalibrationString == "scaled") {
4080 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
4081 } else if (distanceCalibrationString != "default") {
4082 ALOGW("Invalid value for touch.distance.calibration: '%s'",
4083 distanceCalibrationString.string());
4084 }
4085 }
4086
4087 out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
4088 out.distanceScale);
4089
4090 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
4091 String8 coverageCalibrationString;
4092 if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
4093 if (coverageCalibrationString == "none") {
4094 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
4095 } else if (coverageCalibrationString == "box") {
4096 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
4097 } else if (coverageCalibrationString != "default") {
4098 ALOGW("Invalid value for touch.coverage.calibration: '%s'",
4099 coverageCalibrationString.string());
4100 }
4101 }
4102}
4103
4104void TouchInputMapper::resolveCalibration() {
4105 // Size
4106 if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
4107 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
4108 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
4109 }
4110 } else {
4111 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
4112 }
4113
4114 // Pressure
4115 if (mRawPointerAxes.pressure.valid) {
4116 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
4117 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
4118 }
4119 } else {
4120 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
4121 }
4122
4123 // Orientation
4124 if (mRawPointerAxes.orientation.valid) {
4125 if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
4126 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
4127 }
4128 } else {
4129 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
4130 }
4131
4132 // Distance
4133 if (mRawPointerAxes.distance.valid) {
4134 if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
4135 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
4136 }
4137 } else {
4138 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
4139 }
4140
4141 // Coverage
4142 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
4143 mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
4144 }
4145}
4146
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004147void TouchInputMapper::dumpCalibration(std::string& dump) {
4148 dump += INDENT3 "Calibration:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004149
4150 // Size
4151 switch (mCalibration.sizeCalibration) {
4152 case Calibration::SIZE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004153 dump += INDENT4 "touch.size.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004154 break;
4155 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004156 dump += INDENT4 "touch.size.calibration: geometric\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004157 break;
4158 case Calibration::SIZE_CALIBRATION_DIAMETER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004159 dump += INDENT4 "touch.size.calibration: diameter\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004160 break;
4161 case Calibration::SIZE_CALIBRATION_BOX:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004162 dump += INDENT4 "touch.size.calibration: box\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004163 break;
4164 case Calibration::SIZE_CALIBRATION_AREA:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004165 dump += INDENT4 "touch.size.calibration: area\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004166 break;
4167 default:
4168 ALOG_ASSERT(false);
4169 }
4170
4171 if (mCalibration.haveSizeScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004172 dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004173 mCalibration.sizeScale);
4174 }
4175
4176 if (mCalibration.haveSizeBias) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004177 dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004178 mCalibration.sizeBias);
4179 }
4180
4181 if (mCalibration.haveSizeIsSummed) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004182 dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004183 toString(mCalibration.sizeIsSummed));
4184 }
4185
4186 // Pressure
4187 switch (mCalibration.pressureCalibration) {
4188 case Calibration::PRESSURE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004189 dump += INDENT4 "touch.pressure.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004190 break;
4191 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004192 dump += INDENT4 "touch.pressure.calibration: physical\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004193 break;
4194 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004195 dump += INDENT4 "touch.pressure.calibration: amplitude\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004196 break;
4197 default:
4198 ALOG_ASSERT(false);
4199 }
4200
4201 if (mCalibration.havePressureScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004202 dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004203 mCalibration.pressureScale);
4204 }
4205
4206 // Orientation
4207 switch (mCalibration.orientationCalibration) {
4208 case Calibration::ORIENTATION_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004209 dump += INDENT4 "touch.orientation.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004210 break;
4211 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004212 dump += INDENT4 "touch.orientation.calibration: interpolated\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004213 break;
4214 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004215 dump += INDENT4 "touch.orientation.calibration: vector\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004216 break;
4217 default:
4218 ALOG_ASSERT(false);
4219 }
4220
4221 // Distance
4222 switch (mCalibration.distanceCalibration) {
4223 case Calibration::DISTANCE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004224 dump += INDENT4 "touch.distance.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004225 break;
4226 case Calibration::DISTANCE_CALIBRATION_SCALED:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004227 dump += INDENT4 "touch.distance.calibration: scaled\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004228 break;
4229 default:
4230 ALOG_ASSERT(false);
4231 }
4232
4233 if (mCalibration.haveDistanceScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004234 dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004235 mCalibration.distanceScale);
4236 }
4237
4238 switch (mCalibration.coverageCalibration) {
4239 case Calibration::COVERAGE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004240 dump += INDENT4 "touch.coverage.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004241 break;
4242 case Calibration::COVERAGE_CALIBRATION_BOX:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004243 dump += INDENT4 "touch.coverage.calibration: box\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004244 break;
4245 default:
4246 ALOG_ASSERT(false);
4247 }
4248}
4249
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004250void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
4251 dump += INDENT3 "Affine Transformation:\n";
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004252
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004253 dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
4254 dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
4255 dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
4256 dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
4257 dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
4258 dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004259}
4260
Jason Gerecke12d6baa2014-01-27 18:34:20 -08004261void TouchInputMapper::updateAffineTransformation() {
Jason Gerecke71b16e82014-03-10 09:47:59 -07004262 mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
4263 mSurfaceOrientation);
Jason Gerecke12d6baa2014-01-27 18:34:20 -08004264}
4265
Michael Wrightd02c5b62014-02-10 15:10:22 -08004266void TouchInputMapper::reset(nsecs_t when) {
4267 mCursorButtonAccumulator.reset(getDevice());
4268 mCursorScrollAccumulator.reset(getDevice());
4269 mTouchButtonAccumulator.reset(getDevice());
4270
4271 mPointerVelocityControl.reset();
4272 mWheelXVelocityControl.reset();
4273 mWheelYVelocityControl.reset();
4274
Michael Wright842500e2015-03-13 17:32:02 -07004275 mRawStatesPending.clear();
4276 mCurrentRawState.clear();
4277 mCurrentCookedState.clear();
4278 mLastRawState.clear();
4279 mLastCookedState.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004280 mPointerUsage = POINTER_USAGE_NONE;
4281 mSentHoverEnter = false;
Michael Wright842500e2015-03-13 17:32:02 -07004282 mHavePointerIds = false;
Michael Wright8e812822015-06-22 16:18:21 +01004283 mCurrentMotionAborted = false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004284 mDownTime = 0;
4285
4286 mCurrentVirtualKey.down = false;
4287
4288 mPointerGesture.reset();
4289 mPointerSimple.reset();
Michael Wright842500e2015-03-13 17:32:02 -07004290 resetExternalStylus();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004291
Yi Kong9b14ac62018-07-17 13:48:38 -07004292 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004293 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4294 mPointerController->clearSpots();
4295 }
4296
4297 InputMapper::reset(when);
4298}
4299
Michael Wright842500e2015-03-13 17:32:02 -07004300void TouchInputMapper::resetExternalStylus() {
4301 mExternalStylusState.clear();
4302 mExternalStylusId = -1;
Michael Wright43fd19f2015-04-21 19:02:58 +01004303 mExternalStylusFusionTimeout = LLONG_MAX;
Michael Wright842500e2015-03-13 17:32:02 -07004304 mExternalStylusDataPending = false;
4305}
4306
Michael Wright43fd19f2015-04-21 19:02:58 +01004307void TouchInputMapper::clearStylusDataPendingFlags() {
4308 mExternalStylusDataPending = false;
4309 mExternalStylusFusionTimeout = LLONG_MAX;
4310}
4311
Michael Wrightd02c5b62014-02-10 15:10:22 -08004312void TouchInputMapper::process(const RawEvent* rawEvent) {
4313 mCursorButtonAccumulator.process(rawEvent);
4314 mCursorScrollAccumulator.process(rawEvent);
4315 mTouchButtonAccumulator.process(rawEvent);
4316
4317 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
4318 sync(rawEvent->when);
4319 }
4320}
4321
4322void TouchInputMapper::sync(nsecs_t when) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004323 const RawState* last = mRawStatesPending.empty() ?
4324 &mCurrentRawState : &mRawStatesPending.back();
Michael Wright842500e2015-03-13 17:32:02 -07004325
4326 // Push a new state.
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004327 mRawStatesPending.emplace_back();
4328
4329 RawState* next = &mRawStatesPending.back();
Michael Wright842500e2015-03-13 17:32:02 -07004330 next->clear();
4331 next->when = when;
4332
Michael Wrightd02c5b62014-02-10 15:10:22 -08004333 // Sync button state.
Michael Wright842500e2015-03-13 17:32:02 -07004334 next->buttonState = mTouchButtonAccumulator.getButtonState()
Michael Wrightd02c5b62014-02-10 15:10:22 -08004335 | mCursorButtonAccumulator.getButtonState();
4336
Michael Wright842500e2015-03-13 17:32:02 -07004337 // Sync scroll
4338 next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
4339 next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004340 mCursorScrollAccumulator.finishSync();
4341
Michael Wright842500e2015-03-13 17:32:02 -07004342 // Sync touch
4343 syncTouch(when, next);
4344
4345 // Assign pointer ids.
4346 if (!mHavePointerIds) {
4347 assignPointerIds(last, next);
4348 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08004349
4350#if DEBUG_RAW_EVENTS
Michael Wright842500e2015-03-13 17:32:02 -07004351 ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
4352 "hovering ids 0x%08x -> 0x%08x",
4353 last->rawPointerData.pointerCount,
4354 next->rawPointerData.pointerCount,
4355 last->rawPointerData.touchingIdBits.value,
4356 next->rawPointerData.touchingIdBits.value,
4357 last->rawPointerData.hoveringIdBits.value,
4358 next->rawPointerData.hoveringIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004359#endif
4360
Michael Wright842500e2015-03-13 17:32:02 -07004361 processRawTouches(false /*timeout*/);
4362}
Michael Wrightd02c5b62014-02-10 15:10:22 -08004363
Michael Wright842500e2015-03-13 17:32:02 -07004364void TouchInputMapper::processRawTouches(bool timeout) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004365 if (mDeviceMode == DEVICE_MODE_DISABLED) {
4366 // Drop all input if the device is disabled.
Michael Wright842500e2015-03-13 17:32:02 -07004367 mCurrentRawState.clear();
4368 mRawStatesPending.clear();
4369 return;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004370 }
4371
Michael Wright842500e2015-03-13 17:32:02 -07004372 // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
4373 // valid and must go through the full cook and dispatch cycle. This ensures that anything
4374 // touching the current state will only observe the events that have been dispatched to the
4375 // rest of the pipeline.
4376 const size_t N = mRawStatesPending.size();
4377 size_t count;
4378 for(count = 0; count < N; count++) {
4379 const RawState& next = mRawStatesPending[count];
4380
4381 // A failure to assign the stylus id means that we're waiting on stylus data
4382 // and so should defer the rest of the pipeline.
4383 if (assignExternalStylusId(next, timeout)) {
4384 break;
4385 }
4386
4387 // All ready to go.
Michael Wright43fd19f2015-04-21 19:02:58 +01004388 clearStylusDataPendingFlags();
Michael Wright842500e2015-03-13 17:32:02 -07004389 mCurrentRawState.copyFrom(next);
Michael Wright43fd19f2015-04-21 19:02:58 +01004390 if (mCurrentRawState.when < mLastRawState.when) {
4391 mCurrentRawState.when = mLastRawState.when;
4392 }
Michael Wright842500e2015-03-13 17:32:02 -07004393 cookAndDispatch(mCurrentRawState.when);
4394 }
4395 if (count != 0) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08004396 mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);
Michael Wright842500e2015-03-13 17:32:02 -07004397 }
4398
Michael Wright842500e2015-03-13 17:32:02 -07004399 if (mExternalStylusDataPending) {
Michael Wright43fd19f2015-04-21 19:02:58 +01004400 if (timeout) {
4401 nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
4402 clearStylusDataPendingFlags();
4403 mCurrentRawState.copyFrom(mLastRawState);
4404#if DEBUG_STYLUS_FUSION
4405 ALOGD("Timeout expired, synthesizing event with new stylus data");
4406#endif
4407 cookAndDispatch(when);
4408 } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
4409 mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
4410 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
4411 }
Michael Wright842500e2015-03-13 17:32:02 -07004412 }
4413}
4414
4415void TouchInputMapper::cookAndDispatch(nsecs_t when) {
4416 // Always start with a clean state.
4417 mCurrentCookedState.clear();
4418
4419 // Apply stylus buttons to current raw state.
4420 applyExternalStylusButtonState(when);
4421
4422 // Handle policy on initial down or hover events.
4423 bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4424 && mCurrentRawState.rawPointerData.pointerCount != 0;
4425
4426 uint32_t policyFlags = 0;
4427 bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
4428 if (initialDown || buttonsPressed) {
4429 // If this is a touch screen, hide the pointer on an initial down.
4430 if (mDeviceMode == DEVICE_MODE_DIRECT) {
4431 getContext()->fadePointer();
4432 }
4433
4434 if (mParameters.wake) {
4435 policyFlags |= POLICY_FLAG_WAKE;
4436 }
4437 }
4438
4439 // Consume raw off-screen touches before cooking pointer data.
4440 // If touches are consumed, subsequent code will not receive any pointer data.
4441 if (consumeRawTouches(when, policyFlags)) {
4442 mCurrentRawState.rawPointerData.clear();
4443 }
4444
4445 // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
4446 // with cooked pointer data that has the same ids and indices as the raw data.
4447 // The following code can use either the raw or cooked data, as needed.
4448 cookPointerData();
4449
4450 // Apply stylus pressure to current cooked state.
4451 applyExternalStylusTouchState(when);
4452
4453 // Synthesize key down from raw buttons if needed.
4454 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004455 mViewport.displayId, policyFlags,
4456 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
Michael Wright842500e2015-03-13 17:32:02 -07004457
4458 // Dispatch the touches either directly or by translation through a pointer on screen.
4459 if (mDeviceMode == DEVICE_MODE_POINTER) {
4460 for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
4461 !idBits.isEmpty(); ) {
4462 uint32_t id = idBits.clearFirstMarkedBit();
4463 const RawPointerData::Pointer& pointer =
4464 mCurrentRawState.rawPointerData.pointerForId(id);
4465 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
4466 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4467 mCurrentCookedState.stylusIdBits.markBit(id);
4468 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
4469 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4470 mCurrentCookedState.fingerIdBits.markBit(id);
4471 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
4472 mCurrentCookedState.mouseIdBits.markBit(id);
4473 }
4474 }
4475 for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
4476 !idBits.isEmpty(); ) {
4477 uint32_t id = idBits.clearFirstMarkedBit();
4478 const RawPointerData::Pointer& pointer =
4479 mCurrentRawState.rawPointerData.pointerForId(id);
4480 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
4481 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4482 mCurrentCookedState.stylusIdBits.markBit(id);
4483 }
4484 }
4485
4486 // Stylus takes precedence over all tools, then mouse, then finger.
4487 PointerUsage pointerUsage = mPointerUsage;
4488 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
4489 mCurrentCookedState.mouseIdBits.clear();
4490 mCurrentCookedState.fingerIdBits.clear();
4491 pointerUsage = POINTER_USAGE_STYLUS;
4492 } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
4493 mCurrentCookedState.fingerIdBits.clear();
4494 pointerUsage = POINTER_USAGE_MOUSE;
4495 } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
4496 isPointerDown(mCurrentRawState.buttonState)) {
4497 pointerUsage = POINTER_USAGE_GESTURES;
4498 }
4499
4500 dispatchPointerUsage(when, policyFlags, pointerUsage);
4501 } else {
4502 if (mDeviceMode == DEVICE_MODE_DIRECT
Yi Kong9b14ac62018-07-17 13:48:38 -07004503 && mConfig.showTouches && mPointerController != nullptr) {
Michael Wright842500e2015-03-13 17:32:02 -07004504 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
4505 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4506
4507 mPointerController->setButtonState(mCurrentRawState.buttonState);
4508 mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
4509 mCurrentCookedState.cookedPointerData.idToIndex,
Arthur Hung7c645402019-01-25 17:45:42 +08004510 mCurrentCookedState.cookedPointerData.touchingIdBits,
4511 mViewport.displayId);
Michael Wright842500e2015-03-13 17:32:02 -07004512 }
4513
Michael Wright8e812822015-06-22 16:18:21 +01004514 if (!mCurrentMotionAborted) {
4515 dispatchButtonRelease(when, policyFlags);
4516 dispatchHoverExit(when, policyFlags);
4517 dispatchTouches(when, policyFlags);
4518 dispatchHoverEnterAndMove(when, policyFlags);
4519 dispatchButtonPress(when, policyFlags);
4520 }
4521
4522 if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
4523 mCurrentMotionAborted = false;
4524 }
Michael Wright842500e2015-03-13 17:32:02 -07004525 }
4526
4527 // Synthesize key up from raw buttons if needed.
4528 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004529 mViewport.displayId, policyFlags,
4530 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004531
4532 // Clear some transient state.
Michael Wright842500e2015-03-13 17:32:02 -07004533 mCurrentRawState.rawVScroll = 0;
4534 mCurrentRawState.rawHScroll = 0;
4535
4536 // Copy current touch to last touch in preparation for the next cycle.
4537 mLastRawState.copyFrom(mCurrentRawState);
4538 mLastCookedState.copyFrom(mCurrentCookedState);
4539}
4540
4541void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
Michael Wright7b159c92015-05-14 14:48:03 +01004542 if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
Michael Wright842500e2015-03-13 17:32:02 -07004543 mCurrentRawState.buttonState |= mExternalStylusState.buttons;
4544 }
4545}
4546
4547void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
Michael Wright53dca3a2015-04-23 17:39:53 +01004548 CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
4549 const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
Michael Wright842500e2015-03-13 17:32:02 -07004550
Michael Wright53dca3a2015-04-23 17:39:53 +01004551 if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
4552 float pressure = mExternalStylusState.pressure;
4553 if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
4554 const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
4555 pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
4556 }
4557 PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
4558 coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
4559
4560 PointerProperties& properties =
4561 currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
Michael Wright842500e2015-03-13 17:32:02 -07004562 if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4563 properties.toolType = mExternalStylusState.toolType;
4564 }
4565 }
4566}
4567
4568bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
4569 if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
4570 return false;
4571 }
4572
4573 const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4574 && state.rawPointerData.pointerCount != 0;
4575 if (initialDown) {
4576 if (mExternalStylusState.pressure != 0.0f) {
4577#if DEBUG_STYLUS_FUSION
4578 ALOGD("Have both stylus and touch data, beginning fusion");
4579#endif
4580 mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
4581 } else if (timeout) {
4582#if DEBUG_STYLUS_FUSION
4583 ALOGD("Timeout expired, assuming touch is not a stylus.");
4584#endif
4585 resetExternalStylus();
4586 } else {
Michael Wright43fd19f2015-04-21 19:02:58 +01004587 if (mExternalStylusFusionTimeout == LLONG_MAX) {
4588 mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
Michael Wright842500e2015-03-13 17:32:02 -07004589 }
4590#if DEBUG_STYLUS_FUSION
4591 ALOGD("No stylus data but stylus is connected, requesting timeout "
Michael Wright43fd19f2015-04-21 19:02:58 +01004592 "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004593#endif
Michael Wright43fd19f2015-04-21 19:02:58 +01004594 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004595 return true;
4596 }
4597 }
4598
4599 // Check if the stylus pointer has gone up.
4600 if (mExternalStylusId != -1 &&
4601 !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
4602#if DEBUG_STYLUS_FUSION
4603 ALOGD("Stylus pointer is going up");
4604#endif
4605 mExternalStylusId = -1;
4606 }
4607
4608 return false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004609}
4610
4611void TouchInputMapper::timeoutExpired(nsecs_t when) {
4612 if (mDeviceMode == DEVICE_MODE_POINTER) {
4613 if (mPointerUsage == POINTER_USAGE_GESTURES) {
4614 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
4615 }
Michael Wright842500e2015-03-13 17:32:02 -07004616 } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
Michael Wright43fd19f2015-04-21 19:02:58 +01004617 if (mExternalStylusFusionTimeout < when) {
Michael Wright842500e2015-03-13 17:32:02 -07004618 processRawTouches(true /*timeout*/);
Michael Wright43fd19f2015-04-21 19:02:58 +01004619 } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
4620 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004621 }
4622 }
4623}
4624
4625void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
Michael Wright4af18b92015-04-20 22:03:54 +01004626 mExternalStylusState.copyFrom(state);
Michael Wright43fd19f2015-04-21 19:02:58 +01004627 if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
Michael Wright842500e2015-03-13 17:32:02 -07004628 // We're either in the middle of a fused stream of data or we're waiting on data before
4629 // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
4630 // data.
Michael Wright842500e2015-03-13 17:32:02 -07004631 mExternalStylusDataPending = true;
Michael Wright842500e2015-03-13 17:32:02 -07004632 processRawTouches(false /*timeout*/);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004633 }
4634}
4635
4636bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
4637 // Check for release of a virtual key.
4638 if (mCurrentVirtualKey.down) {
Michael Wright842500e2015-03-13 17:32:02 -07004639 if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004640 // Pointer went up while virtual key was down.
4641 mCurrentVirtualKey.down = false;
4642 if (!mCurrentVirtualKey.ignored) {
4643#if DEBUG_VIRTUAL_KEYS
4644 ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
4645 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4646#endif
4647 dispatchVirtualKey(when, policyFlags,
4648 AKEY_EVENT_ACTION_UP,
4649 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4650 }
4651 return true;
4652 }
4653
Michael Wright842500e2015-03-13 17:32:02 -07004654 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
4655 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4656 const RawPointerData::Pointer& pointer =
4657 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004658 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4659 if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
4660 // Pointer is still within the space of the virtual key.
4661 return true;
4662 }
4663 }
4664
4665 // Pointer left virtual key area or another pointer also went down.
4666 // Send key cancellation but do not consume the touch yet.
4667 // This is useful when the user swipes through from the virtual key area
4668 // into the main display surface.
4669 mCurrentVirtualKey.down = false;
4670 if (!mCurrentVirtualKey.ignored) {
4671#if DEBUG_VIRTUAL_KEYS
4672 ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
4673 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4674#endif
4675 dispatchVirtualKey(when, policyFlags,
4676 AKEY_EVENT_ACTION_UP,
4677 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4678 | AKEY_EVENT_FLAG_CANCELED);
4679 }
4680 }
4681
Michael Wright842500e2015-03-13 17:32:02 -07004682 if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
4683 && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004684 // Pointer just went down. Check for virtual key press or off-screen touches.
Michael Wright842500e2015-03-13 17:32:02 -07004685 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4686 const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004687 if (!isPointInsideSurface(pointer.x, pointer.y)) {
4688 // If exactly one pointer went down, check for virtual key hit.
4689 // Otherwise we will drop the entire stroke.
Michael Wright842500e2015-03-13 17:32:02 -07004690 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004691 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4692 if (virtualKey) {
4693 mCurrentVirtualKey.down = true;
4694 mCurrentVirtualKey.downTime = when;
4695 mCurrentVirtualKey.keyCode = virtualKey->keyCode;
4696 mCurrentVirtualKey.scanCode = virtualKey->scanCode;
4697 mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
4698 when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
4699
4700 if (!mCurrentVirtualKey.ignored) {
4701#if DEBUG_VIRTUAL_KEYS
4702 ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
4703 mCurrentVirtualKey.keyCode,
4704 mCurrentVirtualKey.scanCode);
4705#endif
4706 dispatchVirtualKey(when, policyFlags,
4707 AKEY_EVENT_ACTION_DOWN,
4708 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4709 }
4710 }
4711 }
4712 return true;
4713 }
4714 }
4715
4716 // Disable all virtual key touches that happen within a short time interval of the
4717 // most recent touch within the screen area. The idea is to filter out stray
4718 // virtual key presses when interacting with the touch screen.
4719 //
4720 // Problems we're trying to solve:
4721 //
4722 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
4723 // virtual key area that is implemented by a separate touch panel and accidentally
4724 // triggers a virtual key.
4725 //
4726 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
4727 // area and accidentally triggers a virtual key. This often happens when virtual keys
4728 // are layed out below the screen near to where the on screen keyboard's space bar
4729 // is displayed.
Michael Wright842500e2015-03-13 17:32:02 -07004730 if (mConfig.virtualKeyQuietTime > 0 &&
4731 !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004732 mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
4733 }
4734 return false;
4735}
4736
4737void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
4738 int32_t keyEventAction, int32_t keyEventFlags) {
4739 int32_t keyCode = mCurrentVirtualKey.keyCode;
4740 int32_t scanCode = mCurrentVirtualKey.scanCode;
4741 nsecs_t downTime = mCurrentVirtualKey.downTime;
4742 int32_t metaState = mContext->getGlobalMetaState();
4743 policyFlags |= POLICY_FLAG_VIRTUAL;
4744
Prabir Pradhan42611e02018-11-27 14:04:02 -08004745 NotifyKeyArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
4746 mViewport.displayId,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004747 policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004748 getListener()->notifyKey(&args);
4749}
4750
Michael Wright8e812822015-06-22 16:18:21 +01004751void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
4752 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4753 if (!currentIdBits.isEmpty()) {
4754 int32_t metaState = getContext()->getGlobalMetaState();
4755 int32_t buttonState = mCurrentCookedState.buttonState;
4756 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
4757 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4758 mCurrentCookedState.cookedPointerData.pointerProperties,
4759 mCurrentCookedState.cookedPointerData.pointerCoords,
4760 mCurrentCookedState.cookedPointerData.idToIndex,
4761 currentIdBits, -1,
4762 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4763 mCurrentMotionAborted = true;
4764 }
4765}
4766
Michael Wrightd02c5b62014-02-10 15:10:22 -08004767void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004768 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4769 BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004770 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01004771 int32_t buttonState = mCurrentCookedState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004772
4773 if (currentIdBits == lastIdBits) {
4774 if (!currentIdBits.isEmpty()) {
4775 // No pointer id changes so this is a move event.
4776 // The listener takes care of batching moves so we don't have to deal with that here.
4777 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004778 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004779 AMOTION_EVENT_EDGE_FLAG_NONE,
Michael Wright842500e2015-03-13 17:32:02 -07004780 mCurrentCookedState.cookedPointerData.pointerProperties,
4781 mCurrentCookedState.cookedPointerData.pointerCoords,
4782 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004783 currentIdBits, -1,
4784 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4785 }
4786 } else {
4787 // There may be pointers going up and pointers going down and pointers moving
4788 // all at the same time.
4789 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
4790 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
4791 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
4792 BitSet32 dispatchedIdBits(lastIdBits.value);
4793
4794 // Update last coordinates of pointers that have moved so that we observe the new
4795 // pointer positions at the same time as other pointers that have just gone up.
4796 bool moveNeeded = updateMovedPointers(
Michael Wright842500e2015-03-13 17:32:02 -07004797 mCurrentCookedState.cookedPointerData.pointerProperties,
4798 mCurrentCookedState.cookedPointerData.pointerCoords,
4799 mCurrentCookedState.cookedPointerData.idToIndex,
4800 mLastCookedState.cookedPointerData.pointerProperties,
4801 mLastCookedState.cookedPointerData.pointerCoords,
4802 mLastCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004803 moveIdBits);
Michael Wright7b159c92015-05-14 14:48:03 +01004804 if (buttonState != mLastCookedState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004805 moveNeeded = true;
4806 }
4807
4808 // Dispatch pointer up events.
4809 while (!upIdBits.isEmpty()) {
4810 uint32_t upId = upIdBits.clearFirstMarkedBit();
4811
4812 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004813 AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004814 mLastCookedState.cookedPointerData.pointerProperties,
4815 mLastCookedState.cookedPointerData.pointerCoords,
4816 mLastCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004817 dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004818 dispatchedIdBits.clearBit(upId);
4819 }
4820
4821 // Dispatch move events if any of the remaining pointers moved from their old locations.
4822 // Although applications receive new locations as part of individual pointer up
4823 // events, they do not generally handle them except when presented in a move event.
Michael Wright43fd19f2015-04-21 19:02:58 +01004824 if (moveNeeded && !moveIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004825 ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
4826 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004827 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004828 mCurrentCookedState.cookedPointerData.pointerProperties,
4829 mCurrentCookedState.cookedPointerData.pointerCoords,
4830 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004831 dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004832 }
4833
4834 // Dispatch pointer down events using the new pointer locations.
4835 while (!downIdBits.isEmpty()) {
4836 uint32_t downId = downIdBits.clearFirstMarkedBit();
4837 dispatchedIdBits.markBit(downId);
4838
4839 if (dispatchedIdBits.count() == 1) {
4840 // First pointer is going down. Set down time.
4841 mDownTime = when;
4842 }
4843
4844 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004845 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004846 mCurrentCookedState.cookedPointerData.pointerProperties,
4847 mCurrentCookedState.cookedPointerData.pointerCoords,
4848 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004849 dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004850 }
4851 }
4852}
4853
4854void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
4855 if (mSentHoverEnter &&
Michael Wright842500e2015-03-13 17:32:02 -07004856 (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
4857 || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004858 int32_t metaState = getContext()->getGlobalMetaState();
4859 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004860 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004861 mLastCookedState.cookedPointerData.pointerProperties,
4862 mLastCookedState.cookedPointerData.pointerCoords,
4863 mLastCookedState.cookedPointerData.idToIndex,
4864 mLastCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004865 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4866 mSentHoverEnter = false;
4867 }
4868}
4869
4870void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004871 if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
4872 && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004873 int32_t metaState = getContext()->getGlobalMetaState();
4874 if (!mSentHoverEnter) {
Michael Wright842500e2015-03-13 17:32:02 -07004875 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
Michael Wright7b159c92015-05-14 14:48:03 +01004876 0, 0, metaState, mCurrentRawState.buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004877 mCurrentCookedState.cookedPointerData.pointerProperties,
4878 mCurrentCookedState.cookedPointerData.pointerCoords,
4879 mCurrentCookedState.cookedPointerData.idToIndex,
4880 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004881 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4882 mSentHoverEnter = true;
4883 }
4884
4885 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004886 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
Michael Wright842500e2015-03-13 17:32:02 -07004887 mCurrentRawState.buttonState, 0,
4888 mCurrentCookedState.cookedPointerData.pointerProperties,
4889 mCurrentCookedState.cookedPointerData.pointerCoords,
4890 mCurrentCookedState.cookedPointerData.idToIndex,
4891 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004892 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4893 }
4894}
4895
Michael Wright7b159c92015-05-14 14:48:03 +01004896void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
4897 BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
4898 const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
4899 const int32_t metaState = getContext()->getGlobalMetaState();
4900 int32_t buttonState = mLastCookedState.buttonState;
4901 while (!releasedButtons.isEmpty()) {
4902 int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
4903 buttonState &= ~actionButton;
4904 dispatchMotion(when, policyFlags, mSource,
4905 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
4906 0, metaState, buttonState, 0,
4907 mCurrentCookedState.cookedPointerData.pointerProperties,
4908 mCurrentCookedState.cookedPointerData.pointerCoords,
4909 mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
4910 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4911 }
4912}
4913
4914void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
4915 BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
4916 const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
4917 const int32_t metaState = getContext()->getGlobalMetaState();
4918 int32_t buttonState = mLastCookedState.buttonState;
4919 while (!pressedButtons.isEmpty()) {
4920 int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
4921 buttonState |= actionButton;
4922 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
4923 0, metaState, buttonState, 0,
4924 mCurrentCookedState.cookedPointerData.pointerProperties,
4925 mCurrentCookedState.cookedPointerData.pointerCoords,
4926 mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
4927 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4928 }
4929}
4930
4931const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
4932 if (!cookedPointerData.touchingIdBits.isEmpty()) {
4933 return cookedPointerData.touchingIdBits;
4934 }
4935 return cookedPointerData.hoveringIdBits;
4936}
4937
Michael Wrightd02c5b62014-02-10 15:10:22 -08004938void TouchInputMapper::cookPointerData() {
Michael Wright842500e2015-03-13 17:32:02 -07004939 uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004940
Michael Wright842500e2015-03-13 17:32:02 -07004941 mCurrentCookedState.cookedPointerData.clear();
4942 mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
4943 mCurrentCookedState.cookedPointerData.hoveringIdBits =
4944 mCurrentRawState.rawPointerData.hoveringIdBits;
4945 mCurrentCookedState.cookedPointerData.touchingIdBits =
4946 mCurrentRawState.rawPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004947
Michael Wright7b159c92015-05-14 14:48:03 +01004948 if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
4949 mCurrentCookedState.buttonState = 0;
4950 } else {
4951 mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
4952 }
4953
Michael Wrightd02c5b62014-02-10 15:10:22 -08004954 // Walk through the the active pointers and map device coordinates onto
4955 // surface coordinates and adjust for display orientation.
4956 for (uint32_t i = 0; i < currentPointerCount; i++) {
Michael Wright842500e2015-03-13 17:32:02 -07004957 const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08004958
4959 // Size
4960 float touchMajor, touchMinor, toolMajor, toolMinor, size;
4961 switch (mCalibration.sizeCalibration) {
4962 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
4963 case Calibration::SIZE_CALIBRATION_DIAMETER:
4964 case Calibration::SIZE_CALIBRATION_BOX:
4965 case Calibration::SIZE_CALIBRATION_AREA:
4966 if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
4967 touchMajor = in.touchMajor;
4968 touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
4969 toolMajor = in.toolMajor;
4970 toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
4971 size = mRawPointerAxes.touchMinor.valid
4972 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4973 } else if (mRawPointerAxes.touchMajor.valid) {
4974 toolMajor = touchMajor = in.touchMajor;
4975 toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
4976 ? in.touchMinor : in.touchMajor;
4977 size = mRawPointerAxes.touchMinor.valid
4978 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4979 } else if (mRawPointerAxes.toolMajor.valid) {
4980 touchMajor = toolMajor = in.toolMajor;
4981 touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
4982 ? in.toolMinor : in.toolMajor;
4983 size = mRawPointerAxes.toolMinor.valid
4984 ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
4985 } else {
4986 ALOG_ASSERT(false, "No touch or tool axes. "
4987 "Size calibration should have been resolved to NONE.");
4988 touchMajor = 0;
4989 touchMinor = 0;
4990 toolMajor = 0;
4991 toolMinor = 0;
4992 size = 0;
4993 }
4994
4995 if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
Michael Wright842500e2015-03-13 17:32:02 -07004996 uint32_t touchingCount =
4997 mCurrentRawState.rawPointerData.touchingIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004998 if (touchingCount > 1) {
4999 touchMajor /= touchingCount;
5000 touchMinor /= touchingCount;
5001 toolMajor /= touchingCount;
5002 toolMinor /= touchingCount;
5003 size /= touchingCount;
5004 }
5005 }
5006
5007 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
5008 touchMajor *= mGeometricScale;
5009 touchMinor *= mGeometricScale;
5010 toolMajor *= mGeometricScale;
5011 toolMinor *= mGeometricScale;
5012 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
5013 touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
5014 touchMinor = touchMajor;
5015 toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
5016 toolMinor = toolMajor;
5017 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
5018 touchMinor = touchMajor;
5019 toolMinor = toolMajor;
5020 }
5021
5022 mCalibration.applySizeScaleAndBias(&touchMajor);
5023 mCalibration.applySizeScaleAndBias(&touchMinor);
5024 mCalibration.applySizeScaleAndBias(&toolMajor);
5025 mCalibration.applySizeScaleAndBias(&toolMinor);
5026 size *= mSizeScale;
5027 break;
5028 default:
5029 touchMajor = 0;
5030 touchMinor = 0;
5031 toolMajor = 0;
5032 toolMinor = 0;
5033 size = 0;
5034 break;
5035 }
5036
5037 // Pressure
5038 float pressure;
5039 switch (mCalibration.pressureCalibration) {
5040 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
5041 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
5042 pressure = in.pressure * mPressureScale;
5043 break;
5044 default:
5045 pressure = in.isHovering ? 0 : 1;
5046 break;
5047 }
5048
5049 // Tilt and Orientation
5050 float tilt;
5051 float orientation;
5052 if (mHaveTilt) {
5053 float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
5054 float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
5055 orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5056 tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5057 } else {
5058 tilt = 0;
5059
5060 switch (mCalibration.orientationCalibration) {
5061 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
5062 orientation = in.orientation * mOrientationScale;
5063 break;
5064 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
5065 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
5066 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
5067 if (c1 != 0 || c2 != 0) {
5068 orientation = atan2f(c1, c2) * 0.5f;
5069 float confidence = hypotf(c1, c2);
5070 float scale = 1.0f + confidence / 16.0f;
5071 touchMajor *= scale;
5072 touchMinor /= scale;
5073 toolMajor *= scale;
5074 toolMinor /= scale;
5075 } else {
5076 orientation = 0;
5077 }
5078 break;
5079 }
5080 default:
5081 orientation = 0;
5082 }
5083 }
5084
5085 // Distance
5086 float distance;
5087 switch (mCalibration.distanceCalibration) {
5088 case Calibration::DISTANCE_CALIBRATION_SCALED:
5089 distance = in.distance * mDistanceScale;
5090 break;
5091 default:
5092 distance = 0;
5093 }
5094
5095 // Coverage
5096 int32_t rawLeft, rawTop, rawRight, rawBottom;
5097 switch (mCalibration.coverageCalibration) {
5098 case Calibration::COVERAGE_CALIBRATION_BOX:
5099 rawLeft = (in.toolMinor & 0xffff0000) >> 16;
5100 rawRight = in.toolMinor & 0x0000ffff;
5101 rawBottom = in.toolMajor & 0x0000ffff;
5102 rawTop = (in.toolMajor & 0xffff0000) >> 16;
5103 break;
5104 default:
5105 rawLeft = rawTop = rawRight = rawBottom = 0;
5106 break;
5107 }
5108
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005109 // Adjust X,Y coords for device calibration
5110 // TODO: Adjust coverage coords?
5111 float xTransformed = in.x, yTransformed = in.y;
5112 mAffineTransform.applyTo(xTransformed, yTransformed);
5113
5114 // Adjust X, Y, and coverage coords for surface orientation.
5115 float x, y;
5116 float left, top, right, bottom;
5117
Michael Wrightd02c5b62014-02-10 15:10:22 -08005118 switch (mSurfaceOrientation) {
5119 case DISPLAY_ORIENTATION_90:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005120 x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5121 y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005122 left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5123 right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5124 bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
5125 top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
5126 orientation -= M_PI_2;
baik.han18a81482015-04-14 19:49:28 +09005127 if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005128 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5129 }
5130 break;
5131 case DISPLAY_ORIENTATION_180:
Michael Wright358bcc72018-08-21 04:01:07 +01005132 x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005133 y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
Michael Wright358bcc72018-08-21 04:01:07 +01005134 left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
5135 right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005136 bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
5137 top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
5138 orientation -= M_PI;
baik.han18a81482015-04-14 19:49:28 +09005139 if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005140 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5141 }
5142 break;
5143 case DISPLAY_ORIENTATION_270:
Michael Wright358bcc72018-08-21 04:01:07 +01005144 x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005145 y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
Michael Wright358bcc72018-08-21 04:01:07 +01005146 left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
5147 right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005148 bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5149 top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5150 orientation += M_PI_2;
baik.han18a81482015-04-14 19:49:28 +09005151 if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005152 orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5153 }
5154 break;
5155 default:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005156 x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5157 y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005158 left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5159 right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5160 bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5161 top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5162 break;
5163 }
5164
5165 // Write output coords.
Michael Wright842500e2015-03-13 17:32:02 -07005166 PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005167 out.clear();
5168 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5169 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5170 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
5171 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
5172 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
5173 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
5174 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
5175 out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
5176 out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
5177 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
5178 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
5179 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
5180 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
5181 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
5182 } else {
5183 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
5184 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
5185 }
5186
5187 // Write output properties.
Michael Wright842500e2015-03-13 17:32:02 -07005188 PointerProperties& properties =
5189 mCurrentCookedState.cookedPointerData.pointerProperties[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005190 uint32_t id = in.id;
5191 properties.clear();
5192 properties.id = id;
5193 properties.toolType = in.toolType;
5194
5195 // Write id index.
Michael Wright842500e2015-03-13 17:32:02 -07005196 mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005197 }
5198}
5199
5200void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
5201 PointerUsage pointerUsage) {
5202 if (pointerUsage != mPointerUsage) {
5203 abortPointerUsage(when, policyFlags);
5204 mPointerUsage = pointerUsage;
5205 }
5206
5207 switch (mPointerUsage) {
5208 case POINTER_USAGE_GESTURES:
5209 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
5210 break;
5211 case POINTER_USAGE_STYLUS:
5212 dispatchPointerStylus(when, policyFlags);
5213 break;
5214 case POINTER_USAGE_MOUSE:
5215 dispatchPointerMouse(when, policyFlags);
5216 break;
5217 default:
5218 break;
5219 }
5220}
5221
5222void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
5223 switch (mPointerUsage) {
5224 case POINTER_USAGE_GESTURES:
5225 abortPointerGestures(when, policyFlags);
5226 break;
5227 case POINTER_USAGE_STYLUS:
5228 abortPointerStylus(when, policyFlags);
5229 break;
5230 case POINTER_USAGE_MOUSE:
5231 abortPointerMouse(when, policyFlags);
5232 break;
5233 default:
5234 break;
5235 }
5236
5237 mPointerUsage = POINTER_USAGE_NONE;
5238}
5239
5240void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
5241 bool isTimeout) {
5242 // Update current gesture coordinates.
5243 bool cancelPreviousGesture, finishPreviousGesture;
5244 bool sendEvents = preparePointerGestures(when,
5245 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
5246 if (!sendEvents) {
5247 return;
5248 }
5249 if (finishPreviousGesture) {
5250 cancelPreviousGesture = false;
5251 }
5252
5253 // Update the pointer presentation and spots.
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005254 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
5255 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005256 if (finishPreviousGesture || cancelPreviousGesture) {
5257 mPointerController->clearSpots();
5258 }
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005259
5260 if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
5261 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
5262 mPointerGesture.currentGestureIdToIndex,
Arthur Hung7c645402019-01-25 17:45:42 +08005263 mPointerGesture.currentGestureIdBits,
5264 mPointerController->getDisplayId());
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005265 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08005266 } else {
5267 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5268 }
5269
5270 // Show or hide the pointer if needed.
5271 switch (mPointerGesture.currentGestureMode) {
5272 case PointerGesture::NEUTRAL:
5273 case PointerGesture::QUIET:
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005274 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
5275 && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005276 // Remind the user of where the pointer is after finishing a gesture with spots.
5277 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
5278 }
5279 break;
5280 case PointerGesture::TAP:
5281 case PointerGesture::TAP_DRAG:
5282 case PointerGesture::BUTTON_CLICK_OR_DRAG:
5283 case PointerGesture::HOVER:
5284 case PointerGesture::PRESS:
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005285 case PointerGesture::SWIPE:
Michael Wrightd02c5b62014-02-10 15:10:22 -08005286 // Unfade the pointer when the current gesture manipulates the
5287 // area directly under the pointer.
5288 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5289 break;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005290 case PointerGesture::FREEFORM:
5291 // Fade the pointer when the current gesture manipulates a different
5292 // area and there are spots to guide the user experience.
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005293 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005294 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5295 } else {
5296 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5297 }
5298 break;
5299 }
5300
5301 // Send events!
5302 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01005303 int32_t buttonState = mCurrentCookedState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005304
5305 // Update last coordinates of pointers that have moved so that we observe the new
5306 // pointer positions at the same time as other pointers that have just gone up.
5307 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
5308 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
5309 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5310 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
5311 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
5312 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
5313 bool moveNeeded = false;
5314 if (down && !cancelPreviousGesture && !finishPreviousGesture
5315 && !mPointerGesture.lastGestureIdBits.isEmpty()
5316 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
5317 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
5318 & mPointerGesture.lastGestureIdBits.value);
5319 moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
5320 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5321 mPointerGesture.lastGestureProperties,
5322 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5323 movedGestureIdBits);
Michael Wright7b159c92015-05-14 14:48:03 +01005324 if (buttonState != mLastCookedState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005325 moveNeeded = true;
5326 }
5327 }
5328
5329 // Send motion events for all pointers that went up or were canceled.
5330 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
5331 if (!dispatchedGestureIdBits.isEmpty()) {
5332 if (cancelPreviousGesture) {
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005333 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
5334 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5335 mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
5336 mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
5337 mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005338
5339 dispatchedGestureIdBits.clear();
5340 } else {
5341 BitSet32 upGestureIdBits;
5342 if (finishPreviousGesture) {
5343 upGestureIdBits = dispatchedGestureIdBits;
5344 } else {
5345 upGestureIdBits.value = dispatchedGestureIdBits.value
5346 & ~mPointerGesture.currentGestureIdBits.value;
5347 }
5348 while (!upGestureIdBits.isEmpty()) {
5349 uint32_t id = upGestureIdBits.clearFirstMarkedBit();
5350
5351 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005352 AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005353 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5354 mPointerGesture.lastGestureProperties,
5355 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5356 dispatchedGestureIdBits, id,
5357 0, 0, mPointerGesture.downTime);
5358
5359 dispatchedGestureIdBits.clearBit(id);
5360 }
5361 }
5362 }
5363
5364 // Send motion events for all pointers that moved.
5365 if (moveNeeded) {
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005366 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
5367 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5368 mPointerGesture.currentGestureProperties,
5369 mPointerGesture.currentGestureCoords,
5370 mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
5371 mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005372 }
5373
5374 // Send motion events for all pointers that went down.
5375 if (down) {
5376 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
5377 & ~dispatchedGestureIdBits.value);
5378 while (!downGestureIdBits.isEmpty()) {
5379 uint32_t id = downGestureIdBits.clearFirstMarkedBit();
5380 dispatchedGestureIdBits.markBit(id);
5381
5382 if (dispatchedGestureIdBits.count() == 1) {
5383 mPointerGesture.downTime = when;
5384 }
5385
5386 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005387 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005388 mPointerGesture.currentGestureProperties,
5389 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5390 dispatchedGestureIdBits, id,
5391 0, 0, mPointerGesture.downTime);
5392 }
5393 }
5394
5395 // Send motion events for hover.
5396 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005397 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
5398 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5399 mPointerGesture.currentGestureProperties,
5400 mPointerGesture.currentGestureCoords,
5401 mPointerGesture.currentGestureIdToIndex,
5402 mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005403 } else if (dispatchedGestureIdBits.isEmpty()
5404 && !mPointerGesture.lastGestureIdBits.isEmpty()) {
5405 // Synthesize a hover move event after all pointers go up to indicate that
5406 // the pointer is hovering again even if the user is not currently touching
5407 // the touch pad. This ensures that a view will receive a fresh hover enter
5408 // event after a tap.
5409 float x, y;
5410 mPointerController->getPosition(&x, &y);
5411
5412 PointerProperties pointerProperties;
5413 pointerProperties.clear();
5414 pointerProperties.id = 0;
5415 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5416
5417 PointerCoords pointerCoords;
5418 pointerCoords.clear();
5419 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5420 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5421
Arthur Hungc7ad2d02018-12-18 17:41:29 +08005422 const int32_t displayId = mPointerController->getDisplayId();
Garfield Tan00f511d2019-06-12 16:55:40 -07005423 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
5424 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
5425 metaState, buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005426 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
5427 0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08005428 getListener()->notifyMotion(&args);
5429 }
5430
5431 // Update state.
5432 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
5433 if (!down) {
5434 mPointerGesture.lastGestureIdBits.clear();
5435 } else {
5436 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
5437 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
5438 uint32_t id = idBits.clearFirstMarkedBit();
5439 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
5440 mPointerGesture.lastGestureProperties[index].copyFrom(
5441 mPointerGesture.currentGestureProperties[index]);
5442 mPointerGesture.lastGestureCoords[index].copyFrom(
5443 mPointerGesture.currentGestureCoords[index]);
5444 mPointerGesture.lastGestureIdToIndex[id] = index;
5445 }
5446 }
5447}
5448
5449void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
5450 // Cancel previously dispatches pointers.
5451 if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
5452 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright842500e2015-03-13 17:32:02 -07005453 int32_t buttonState = mCurrentRawState.buttonState;
Atif Niyaz21da0ff2019-06-28 13:22:51 -07005454 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState,
5455 buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5456 mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
5457 mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
5458 0, 0, mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005459 }
5460
5461 // Reset the current pointer gesture.
5462 mPointerGesture.reset();
5463 mPointerVelocityControl.reset();
5464
5465 // Remove any current spots.
Yi Kong9b14ac62018-07-17 13:48:38 -07005466 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005467 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5468 mPointerController->clearSpots();
5469 }
5470}
5471
5472bool TouchInputMapper::preparePointerGestures(nsecs_t when,
5473 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
5474 *outCancelPreviousGesture = false;
5475 *outFinishPreviousGesture = false;
5476
5477 // Handle TAP timeout.
5478 if (isTimeout) {
5479#if DEBUG_GESTURES
5480 ALOGD("Gestures: Processing timeout");
5481#endif
5482
5483 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5484 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5485 // The tap/drag timeout has not yet expired.
5486 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
5487 + mConfig.pointerGestureTapDragInterval);
5488 } else {
5489 // The tap is finished.
5490#if DEBUG_GESTURES
5491 ALOGD("Gestures: TAP finished");
5492#endif
5493 *outFinishPreviousGesture = true;
5494
5495 mPointerGesture.activeGestureId = -1;
5496 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5497 mPointerGesture.currentGestureIdBits.clear();
5498
5499 mPointerVelocityControl.reset();
5500 return true;
5501 }
5502 }
5503
5504 // We did not handle this timeout.
5505 return false;
5506 }
5507
Michael Wright842500e2015-03-13 17:32:02 -07005508 const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
5509 const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005510
5511 // Update the velocity tracker.
5512 {
5513 VelocityTracker::Position positions[MAX_POINTERS];
5514 uint32_t count = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005515 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005516 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005517 const RawPointerData::Pointer& pointer =
5518 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005519 positions[count].x = pointer.x * mPointerXMovementScale;
5520 positions[count].y = pointer.y * mPointerYMovementScale;
5521 }
5522 mPointerGesture.velocityTracker.addMovement(when,
Michael Wright842500e2015-03-13 17:32:02 -07005523 mCurrentCookedState.fingerIdBits, positions);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005524 }
5525
5526 // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
5527 // to NEUTRAL, then we should not generate tap event.
5528 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
5529 && mPointerGesture.lastGestureMode != PointerGesture::TAP
5530 && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
5531 mPointerGesture.resetTap();
5532 }
5533
5534 // Pick a new active touch id if needed.
5535 // Choose an arbitrary pointer that just went down, if there is one.
5536 // Otherwise choose an arbitrary remaining pointer.
5537 // This guarantees we always have an active touch id when there is at least one pointer.
5538 // We keep the same active touch id for as long as possible.
Michael Wrightd02c5b62014-02-10 15:10:22 -08005539 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
5540 int32_t activeTouchId = lastActiveTouchId;
5541 if (activeTouchId < 0) {
Michael Wright842500e2015-03-13 17:32:02 -07005542 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005543 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07005544 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005545 mPointerGesture.firstTouchTime = when;
5546 }
Michael Wright842500e2015-03-13 17:32:02 -07005547 } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wright842500e2015-03-13 17:32:02 -07005548 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005549 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07005550 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005551 } else {
5552 activeTouchId = mPointerGesture.activeTouchId = -1;
5553 }
5554 }
5555
5556 // Determine whether we are in quiet time.
5557 bool isQuietTime = false;
5558 if (activeTouchId < 0) {
5559 mPointerGesture.resetQuietTime();
5560 } else {
5561 isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
5562 if (!isQuietTime) {
5563 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
5564 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
5565 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
5566 && currentFingerCount < 2) {
5567 // Enter quiet time when exiting swipe or freeform state.
5568 // This is to prevent accidentally entering the hover state and flinging the
5569 // pointer when finishing a swipe and there is still one pointer left onscreen.
5570 isQuietTime = true;
5571 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5572 && currentFingerCount >= 2
Michael Wright842500e2015-03-13 17:32:02 -07005573 && !isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005574 // Enter quiet time when releasing the button and there are still two or more
5575 // fingers down. This may indicate that one finger was used to press the button
5576 // but it has not gone up yet.
5577 isQuietTime = true;
5578 }
5579 if (isQuietTime) {
5580 mPointerGesture.quietTime = when;
5581 }
5582 }
5583 }
5584
5585 // Switch states based on button and pointer state.
5586 if (isQuietTime) {
5587 // Case 1: Quiet time. (QUIET)
5588#if DEBUG_GESTURES
5589 ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
5590 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
5591#endif
5592 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
5593 *outFinishPreviousGesture = true;
5594 }
5595
5596 mPointerGesture.activeGestureId = -1;
5597 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
5598 mPointerGesture.currentGestureIdBits.clear();
5599
5600 mPointerVelocityControl.reset();
Michael Wright842500e2015-03-13 17:32:02 -07005601 } else if (isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005602 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
5603 // The pointer follows the active touch point.
5604 // Emit DOWN, MOVE, UP events at the pointer location.
5605 //
5606 // Only the active touch matters; other fingers are ignored. This policy helps
5607 // to handle the case where the user places a second finger on the touch pad
5608 // to apply the necessary force to depress an integrated button below the surface.
5609 // We don't want the second finger to be delivered to applications.
5610 //
5611 // For this to work well, we need to make sure to track the pointer that is really
5612 // active. If the user first puts one finger down to click then adds another
5613 // finger to drag then the active pointer should switch to the finger that is
5614 // being dragged.
5615#if DEBUG_GESTURES
5616 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
5617 "currentFingerCount=%d", activeTouchId, currentFingerCount);
5618#endif
5619 // Reset state when just starting.
5620 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
5621 *outFinishPreviousGesture = true;
5622 mPointerGesture.activeGestureId = 0;
5623 }
5624
5625 // Switch pointers if needed.
5626 // Find the fastest pointer and follow it.
5627 if (activeTouchId >= 0 && currentFingerCount > 1) {
5628 int32_t bestId = -1;
5629 float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
Michael Wright842500e2015-03-13 17:32:02 -07005630 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005631 uint32_t id = idBits.clearFirstMarkedBit();
5632 float vx, vy;
5633 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
5634 float speed = hypotf(vx, vy);
5635 if (speed > bestSpeed) {
5636 bestId = id;
5637 bestSpeed = speed;
5638 }
5639 }
5640 }
5641 if (bestId >= 0 && bestId != activeTouchId) {
5642 mPointerGesture.activeTouchId = activeTouchId = bestId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005643#if DEBUG_GESTURES
5644 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
5645 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
5646#endif
5647 }
5648 }
5649
Jun Mukaifa1706a2015-12-03 01:14:46 -08005650 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005651 if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005652 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005653 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005654 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005655 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Jun Mukaifa1706a2015-12-03 01:14:46 -08005656 deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5657 deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005658
5659 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5660 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5661
5662 // Move the pointer using a relative motion.
5663 // When using spots, the click will occur at the position of the anchor
5664 // spot and all other spots will move there.
5665 mPointerController->move(deltaX, deltaY);
5666 } else {
5667 mPointerVelocityControl.reset();
5668 }
5669
5670 float x, y;
5671 mPointerController->getPosition(&x, &y);
5672
5673 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
5674 mPointerGesture.currentGestureIdBits.clear();
5675 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5676 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5677 mPointerGesture.currentGestureProperties[0].clear();
5678 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5679 mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5680 mPointerGesture.currentGestureCoords[0].clear();
5681 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5682 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5683 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5684 } else if (currentFingerCount == 0) {
5685 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
5686 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
5687 *outFinishPreviousGesture = true;
5688 }
5689
5690 // Watch for taps coming out of HOVER or TAP_DRAG mode.
5691 // Checking for taps after TAP_DRAG allows us to detect double-taps.
5692 bool tapped = false;
5693 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
5694 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
5695 && lastFingerCount == 1) {
5696 if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
5697 float x, y;
5698 mPointerController->getPosition(&x, &y);
5699 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5700 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5701#if DEBUG_GESTURES
5702 ALOGD("Gestures: TAP");
5703#endif
5704
5705 mPointerGesture.tapUpTime = when;
5706 getContext()->requestTimeoutAtTime(when
5707 + mConfig.pointerGestureTapDragInterval);
5708
5709 mPointerGesture.activeGestureId = 0;
5710 mPointerGesture.currentGestureMode = PointerGesture::TAP;
5711 mPointerGesture.currentGestureIdBits.clear();
5712 mPointerGesture.currentGestureIdBits.markBit(
5713 mPointerGesture.activeGestureId);
5714 mPointerGesture.currentGestureIdToIndex[
5715 mPointerGesture.activeGestureId] = 0;
5716 mPointerGesture.currentGestureProperties[0].clear();
5717 mPointerGesture.currentGestureProperties[0].id =
5718 mPointerGesture.activeGestureId;
5719 mPointerGesture.currentGestureProperties[0].toolType =
5720 AMOTION_EVENT_TOOL_TYPE_FINGER;
5721 mPointerGesture.currentGestureCoords[0].clear();
5722 mPointerGesture.currentGestureCoords[0].setAxisValue(
5723 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
5724 mPointerGesture.currentGestureCoords[0].setAxisValue(
5725 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
5726 mPointerGesture.currentGestureCoords[0].setAxisValue(
5727 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5728
5729 tapped = true;
5730 } else {
5731#if DEBUG_GESTURES
5732 ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
5733 x - mPointerGesture.tapX,
5734 y - mPointerGesture.tapY);
5735#endif
5736 }
5737 } else {
5738#if DEBUG_GESTURES
5739 if (mPointerGesture.tapDownTime != LLONG_MIN) {
5740 ALOGD("Gestures: Not a TAP, %0.3fms since down",
5741 (when - mPointerGesture.tapDownTime) * 0.000001f);
5742 } else {
5743 ALOGD("Gestures: Not a TAP, incompatible mode transitions");
5744 }
5745#endif
5746 }
5747 }
5748
5749 mPointerVelocityControl.reset();
5750
5751 if (!tapped) {
5752#if DEBUG_GESTURES
5753 ALOGD("Gestures: NEUTRAL");
5754#endif
5755 mPointerGesture.activeGestureId = -1;
5756 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5757 mPointerGesture.currentGestureIdBits.clear();
5758 }
5759 } else if (currentFingerCount == 1) {
5760 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
5761 // The pointer follows the active touch point.
5762 // When in HOVER, emit HOVER_MOVE events at the pointer location.
5763 // When in TAP_DRAG, emit MOVE events at the pointer location.
5764 ALOG_ASSERT(activeTouchId >= 0);
5765
5766 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
5767 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5768 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5769 float x, y;
5770 mPointerController->getPosition(&x, &y);
5771 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5772 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5773 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5774 } else {
5775#if DEBUG_GESTURES
5776 ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
5777 x - mPointerGesture.tapX,
5778 y - mPointerGesture.tapY);
5779#endif
5780 }
5781 } else {
5782#if DEBUG_GESTURES
5783 ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
5784 (when - mPointerGesture.tapUpTime) * 0.000001f);
5785#endif
5786 }
5787 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
5788 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5789 }
5790
Jun Mukaifa1706a2015-12-03 01:14:46 -08005791 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005792 if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005793 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005794 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005795 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005796 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Jun Mukaifa1706a2015-12-03 01:14:46 -08005797 deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5798 deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005799
5800 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5801 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5802
5803 // Move the pointer using a relative motion.
5804 // When using spots, the hover or drag will occur at the position of the anchor spot.
5805 mPointerController->move(deltaX, deltaY);
5806 } else {
5807 mPointerVelocityControl.reset();
5808 }
5809
5810 bool down;
5811 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
5812#if DEBUG_GESTURES
5813 ALOGD("Gestures: TAP_DRAG");
5814#endif
5815 down = true;
5816 } else {
5817#if DEBUG_GESTURES
5818 ALOGD("Gestures: HOVER");
5819#endif
5820 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
5821 *outFinishPreviousGesture = true;
5822 }
5823 mPointerGesture.activeGestureId = 0;
5824 down = false;
5825 }
5826
5827 float x, y;
5828 mPointerController->getPosition(&x, &y);
5829
5830 mPointerGesture.currentGestureIdBits.clear();
5831 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5832 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5833 mPointerGesture.currentGestureProperties[0].clear();
5834 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5835 mPointerGesture.currentGestureProperties[0].toolType =
5836 AMOTION_EVENT_TOOL_TYPE_FINGER;
5837 mPointerGesture.currentGestureCoords[0].clear();
5838 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5839 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5840 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5841 down ? 1.0f : 0.0f);
5842
5843 if (lastFingerCount == 0 && currentFingerCount != 0) {
5844 mPointerGesture.resetTap();
5845 mPointerGesture.tapDownTime = when;
5846 mPointerGesture.tapX = x;
5847 mPointerGesture.tapY = y;
5848 }
5849 } else {
5850 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
5851 // We need to provide feedback for each finger that goes down so we cannot wait
5852 // for the fingers to move before deciding what to do.
5853 //
5854 // The ambiguous case is deciding what to do when there are two fingers down but they
5855 // have not moved enough to determine whether they are part of a drag or part of a
5856 // freeform gesture, or just a press or long-press at the pointer location.
5857 //
5858 // When there are two fingers we start with the PRESS hypothesis and we generate a
5859 // down at the pointer location.
5860 //
5861 // When the two fingers move enough or when additional fingers are added, we make
5862 // a decision to transition into SWIPE or FREEFORM mode accordingly.
5863 ALOG_ASSERT(activeTouchId >= 0);
5864
5865 bool settled = when >= mPointerGesture.firstTouchTime
5866 + mConfig.pointerGestureMultitouchSettleInterval;
5867 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
5868 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
5869 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5870 *outFinishPreviousGesture = true;
5871 } else if (!settled && currentFingerCount > lastFingerCount) {
5872 // Additional pointers have gone down but not yet settled.
5873 // Reset the gesture.
5874#if DEBUG_GESTURES
5875 ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
5876 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5877 + mConfig.pointerGestureMultitouchSettleInterval - when)
5878 * 0.000001f);
5879#endif
5880 *outCancelPreviousGesture = true;
5881 } else {
5882 // Continue previous gesture.
5883 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
5884 }
5885
5886 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
5887 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
5888 mPointerGesture.activeGestureId = 0;
5889 mPointerGesture.referenceIdBits.clear();
5890 mPointerVelocityControl.reset();
5891
5892 // Use the centroid and pointer location as the reference points for the gesture.
5893#if DEBUG_GESTURES
5894 ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
5895 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5896 + mConfig.pointerGestureMultitouchSettleInterval - when)
5897 * 0.000001f);
5898#endif
Michael Wright842500e2015-03-13 17:32:02 -07005899 mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
Michael Wrightd02c5b62014-02-10 15:10:22 -08005900 &mPointerGesture.referenceTouchX,
5901 &mPointerGesture.referenceTouchY);
5902 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
5903 &mPointerGesture.referenceGestureY);
5904 }
5905
5906 // Clear the reference deltas for fingers not yet included in the reference calculation.
Michael Wright842500e2015-03-13 17:32:02 -07005907 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
Michael Wrightd02c5b62014-02-10 15:10:22 -08005908 & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
5909 uint32_t id = idBits.clearFirstMarkedBit();
5910 mPointerGesture.referenceDeltas[id].dx = 0;
5911 mPointerGesture.referenceDeltas[id].dy = 0;
5912 }
Michael Wright842500e2015-03-13 17:32:02 -07005913 mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005914
5915 // Add delta for all fingers and calculate a common movement delta.
5916 float commonDeltaX = 0, commonDeltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005917 BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
5918 & mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005919 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
5920 bool first = (idBits == commonIdBits);
5921 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005922 const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
5923 const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005924 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5925 delta.dx += cpd.x - lpd.x;
5926 delta.dy += cpd.y - lpd.y;
5927
5928 if (first) {
5929 commonDeltaX = delta.dx;
5930 commonDeltaY = delta.dy;
5931 } else {
5932 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
5933 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
5934 }
5935 }
5936
5937 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
5938 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
5939 float dist[MAX_POINTER_ID + 1];
5940 int32_t distOverThreshold = 0;
5941 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
5942 uint32_t id = idBits.clearFirstMarkedBit();
5943 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5944 dist[id] = hypotf(delta.dx * mPointerXZoomScale,
5945 delta.dy * mPointerYZoomScale);
5946 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
5947 distOverThreshold += 1;
5948 }
5949 }
5950
5951 // Only transition when at least two pointers have moved further than
5952 // the minimum distance threshold.
5953 if (distOverThreshold >= 2) {
5954 if (currentFingerCount > 2) {
5955 // There are more than two pointers, switch to FREEFORM.
5956#if DEBUG_GESTURES
5957 ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
5958 currentFingerCount);
5959#endif
5960 *outCancelPreviousGesture = true;
5961 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5962 } else {
5963 // There are exactly two pointers.
Michael Wright842500e2015-03-13 17:32:02 -07005964 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005965 uint32_t id1 = idBits.clearFirstMarkedBit();
5966 uint32_t id2 = idBits.firstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005967 const RawPointerData::Pointer& p1 =
5968 mCurrentRawState.rawPointerData.pointerForId(id1);
5969 const RawPointerData::Pointer& p2 =
5970 mCurrentRawState.rawPointerData.pointerForId(id2);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005971 float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
5972 if (mutualDistance > mPointerGestureMaxSwipeWidth) {
5973 // There are two pointers but they are too far apart for a SWIPE,
5974 // switch to FREEFORM.
5975#if DEBUG_GESTURES
5976 ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
5977 mutualDistance, mPointerGestureMaxSwipeWidth);
5978#endif
5979 *outCancelPreviousGesture = true;
5980 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5981 } else {
5982 // There are two pointers. Wait for both pointers to start moving
5983 // before deciding whether this is a SWIPE or FREEFORM gesture.
5984 float dist1 = dist[id1];
5985 float dist2 = dist[id2];
5986 if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
5987 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
5988 // Calculate the dot product of the displacement vectors.
5989 // When the vectors are oriented in approximately the same direction,
5990 // the angle betweeen them is near zero and the cosine of the angle
5991 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
5992 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
5993 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
5994 float dx1 = delta1.dx * mPointerXZoomScale;
5995 float dy1 = delta1.dy * mPointerYZoomScale;
5996 float dx2 = delta2.dx * mPointerXZoomScale;
5997 float dy2 = delta2.dy * mPointerYZoomScale;
5998 float dot = dx1 * dx2 + dy1 * dy2;
5999 float cosine = dot / (dist1 * dist2); // denominator always > 0
6000 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
6001 // Pointers are moving in the same direction. Switch to SWIPE.
6002#if DEBUG_GESTURES
6003 ALOGD("Gestures: PRESS transitioned to SWIPE, "
6004 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
6005 "cosine %0.3f >= %0.3f",
6006 dist1, mConfig.pointerGestureMultitouchMinDistance,
6007 dist2, mConfig.pointerGestureMultitouchMinDistance,
6008 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
6009#endif
6010 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
6011 } else {
6012 // Pointers are moving in different directions. Switch to FREEFORM.
6013#if DEBUG_GESTURES
6014 ALOGD("Gestures: PRESS transitioned to FREEFORM, "
6015 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
6016 "cosine %0.3f < %0.3f",
6017 dist1, mConfig.pointerGestureMultitouchMinDistance,
6018 dist2, mConfig.pointerGestureMultitouchMinDistance,
6019 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
6020#endif
6021 *outCancelPreviousGesture = true;
6022 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6023 }
6024 }
6025 }
6026 }
6027 }
6028 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
6029 // Switch from SWIPE to FREEFORM if additional pointers go down.
6030 // Cancel previous gesture.
6031 if (currentFingerCount > 2) {
6032#if DEBUG_GESTURES
6033 ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
6034 currentFingerCount);
6035#endif
6036 *outCancelPreviousGesture = true;
6037 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6038 }
6039 }
6040
6041 // Move the reference points based on the overall group motion of the fingers
6042 // except in PRESS mode while waiting for a transition to occur.
6043 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
6044 && (commonDeltaX || commonDeltaY)) {
6045 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
6046 uint32_t id = idBits.clearFirstMarkedBit();
6047 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
6048 delta.dx = 0;
6049 delta.dy = 0;
6050 }
6051
6052 mPointerGesture.referenceTouchX += commonDeltaX;
6053 mPointerGesture.referenceTouchY += commonDeltaY;
6054
6055 commonDeltaX *= mPointerXMovementScale;
6056 commonDeltaY *= mPointerYMovementScale;
6057
6058 rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
6059 mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
6060
6061 mPointerGesture.referenceGestureX += commonDeltaX;
6062 mPointerGesture.referenceGestureY += commonDeltaY;
6063 }
6064
6065 // Report gestures.
6066 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
6067 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
6068 // PRESS or SWIPE mode.
6069#if DEBUG_GESTURES
6070 ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
6071 "activeGestureId=%d, currentTouchPointerCount=%d",
6072 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
6073#endif
6074 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
6075
6076 mPointerGesture.currentGestureIdBits.clear();
6077 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
6078 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
6079 mPointerGesture.currentGestureProperties[0].clear();
6080 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
6081 mPointerGesture.currentGestureProperties[0].toolType =
6082 AMOTION_EVENT_TOOL_TYPE_FINGER;
6083 mPointerGesture.currentGestureCoords[0].clear();
6084 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6085 mPointerGesture.referenceGestureX);
6086 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
6087 mPointerGesture.referenceGestureY);
6088 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
6089 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
6090 // FREEFORM mode.
6091#if DEBUG_GESTURES
6092 ALOGD("Gestures: FREEFORM activeTouchId=%d,"
6093 "activeGestureId=%d, currentTouchPointerCount=%d",
6094 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
6095#endif
6096 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
6097
6098 mPointerGesture.currentGestureIdBits.clear();
6099
6100 BitSet32 mappedTouchIdBits;
6101 BitSet32 usedGestureIdBits;
6102 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
6103 // Initially, assign the active gesture id to the active touch point
6104 // if there is one. No other touch id bits are mapped yet.
6105 if (!*outCancelPreviousGesture) {
6106 mappedTouchIdBits.markBit(activeTouchId);
6107 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
6108 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
6109 mPointerGesture.activeGestureId;
6110 } else {
6111 mPointerGesture.activeGestureId = -1;
6112 }
6113 } else {
6114 // Otherwise, assume we mapped all touches from the previous frame.
6115 // Reuse all mappings that are still applicable.
Michael Wright842500e2015-03-13 17:32:02 -07006116 mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
6117 & mCurrentCookedState.fingerIdBits.value;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006118 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
6119
6120 // Check whether we need to choose a new active gesture id because the
6121 // current went went up.
Michael Wright842500e2015-03-13 17:32:02 -07006122 for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
6123 & ~mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006124 !upTouchIdBits.isEmpty(); ) {
6125 uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
6126 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
6127 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
6128 mPointerGesture.activeGestureId = -1;
6129 break;
6130 }
6131 }
6132 }
6133
6134#if DEBUG_GESTURES
6135 ALOGD("Gestures: FREEFORM follow up "
6136 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
6137 "activeGestureId=%d",
6138 mappedTouchIdBits.value, usedGestureIdBits.value,
6139 mPointerGesture.activeGestureId);
6140#endif
6141
Michael Wright842500e2015-03-13 17:32:02 -07006142 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006143 for (uint32_t i = 0; i < currentFingerCount; i++) {
6144 uint32_t touchId = idBits.clearFirstMarkedBit();
6145 uint32_t gestureId;
6146 if (!mappedTouchIdBits.hasBit(touchId)) {
6147 gestureId = usedGestureIdBits.markFirstUnmarkedBit();
6148 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
6149#if DEBUG_GESTURES
6150 ALOGD("Gestures: FREEFORM "
6151 "new mapping for touch id %d -> gesture id %d",
6152 touchId, gestureId);
6153#endif
6154 } else {
6155 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
6156#if DEBUG_GESTURES
6157 ALOGD("Gestures: FREEFORM "
6158 "existing mapping for touch id %d -> gesture id %d",
6159 touchId, gestureId);
6160#endif
6161 }
6162 mPointerGesture.currentGestureIdBits.markBit(gestureId);
6163 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
6164
6165 const RawPointerData::Pointer& pointer =
Michael Wright842500e2015-03-13 17:32:02 -07006166 mCurrentRawState.rawPointerData.pointerForId(touchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006167 float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
6168 * mPointerXZoomScale;
6169 float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
6170 * mPointerYZoomScale;
6171 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
6172
6173 mPointerGesture.currentGestureProperties[i].clear();
6174 mPointerGesture.currentGestureProperties[i].id = gestureId;
6175 mPointerGesture.currentGestureProperties[i].toolType =
6176 AMOTION_EVENT_TOOL_TYPE_FINGER;
6177 mPointerGesture.currentGestureCoords[i].clear();
6178 mPointerGesture.currentGestureCoords[i].setAxisValue(
6179 AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
6180 mPointerGesture.currentGestureCoords[i].setAxisValue(
6181 AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
6182 mPointerGesture.currentGestureCoords[i].setAxisValue(
6183 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
6184 }
6185
6186 if (mPointerGesture.activeGestureId < 0) {
6187 mPointerGesture.activeGestureId =
6188 mPointerGesture.currentGestureIdBits.firstMarkedBit();
6189#if DEBUG_GESTURES
6190 ALOGD("Gestures: FREEFORM new "
6191 "activeGestureId=%d", mPointerGesture.activeGestureId);
6192#endif
6193 }
6194 }
6195 }
6196
Michael Wright842500e2015-03-13 17:32:02 -07006197 mPointerController->setButtonState(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006198
6199#if DEBUG_GESTURES
6200 ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
6201 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
6202 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
6203 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
6204 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
6205 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
6206 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
6207 uint32_t id = idBits.clearFirstMarkedBit();
6208 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
6209 const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
6210 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
6211 ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
6212 "x=%0.3f, y=%0.3f, pressure=%0.3f",
6213 id, index, properties.toolType,
6214 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
6215 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
6216 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
6217 }
6218 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
6219 uint32_t id = idBits.clearFirstMarkedBit();
6220 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
6221 const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
6222 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
6223 ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
6224 "x=%0.3f, y=%0.3f, pressure=%0.3f",
6225 id, index, properties.toolType,
6226 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
6227 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
6228 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
6229 }
6230#endif
6231 return true;
6232}
6233
6234void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
6235 mPointerSimple.currentCoords.clear();
6236 mPointerSimple.currentProperties.clear();
6237
6238 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07006239 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
6240 uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
6241 uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
6242 float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
6243 float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006244 mPointerController->setPosition(x, y);
6245
Michael Wright842500e2015-03-13 17:32:02 -07006246 hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006247 down = !hovering;
6248
6249 mPointerController->getPosition(&x, &y);
Michael Wright842500e2015-03-13 17:32:02 -07006250 mPointerSimple.currentCoords.copyFrom(
6251 mCurrentCookedState.cookedPointerData.pointerCoords[index]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006252 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
6253 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
6254 mPointerSimple.currentProperties.id = 0;
6255 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07006256 mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006257 } else {
6258 down = false;
6259 hovering = false;
6260 }
6261
6262 dispatchPointerSimple(when, policyFlags, down, hovering);
6263}
6264
6265void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
6266 abortPointerSimple(when, policyFlags);
6267}
6268
6269void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
6270 mPointerSimple.currentCoords.clear();
6271 mPointerSimple.currentProperties.clear();
6272
6273 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07006274 if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
6275 uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
6276 uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
Jun Mukaifa1706a2015-12-03 01:14:46 -08006277 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07006278 if (mLastCookedState.mouseIdBits.hasBit(id)) {
6279 uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
Jun Mukaifa1706a2015-12-03 01:14:46 -08006280 deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
Michael Wright842500e2015-03-13 17:32:02 -07006281 - mLastRawState.rawPointerData.pointers[lastIndex].x)
Michael Wrightd02c5b62014-02-10 15:10:22 -08006282 * mPointerXMovementScale;
Jun Mukaifa1706a2015-12-03 01:14:46 -08006283 deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
Michael Wright842500e2015-03-13 17:32:02 -07006284 - mLastRawState.rawPointerData.pointers[lastIndex].y)
Michael Wrightd02c5b62014-02-10 15:10:22 -08006285 * mPointerYMovementScale;
6286
6287 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
6288 mPointerVelocityControl.move(when, &deltaX, &deltaY);
6289
6290 mPointerController->move(deltaX, deltaY);
6291 } else {
6292 mPointerVelocityControl.reset();
6293 }
6294
Michael Wright842500e2015-03-13 17:32:02 -07006295 down = isPointerDown(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006296 hovering = !down;
6297
6298 float x, y;
6299 mPointerController->getPosition(&x, &y);
6300 mPointerSimple.currentCoords.copyFrom(
Michael Wright842500e2015-03-13 17:32:02 -07006301 mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006302 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
6303 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
6304 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
6305 hovering ? 0.0f : 1.0f);
6306 mPointerSimple.currentProperties.id = 0;
6307 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07006308 mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006309 } else {
6310 mPointerVelocityControl.reset();
6311
6312 down = false;
6313 hovering = false;
6314 }
6315
6316 dispatchPointerSimple(when, policyFlags, down, hovering);
6317}
6318
6319void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
6320 abortPointerSimple(when, policyFlags);
6321
6322 mPointerVelocityControl.reset();
6323}
6324
6325void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
6326 bool down, bool hovering) {
6327 int32_t metaState = getContext()->getGlobalMetaState();
Arthur Hungc7ad2d02018-12-18 17:41:29 +08006328 int32_t displayId = mViewport.displayId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006329
Garfield Tan00f511d2019-06-12 16:55:40 -07006330 if (down || hovering) {
6331 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
6332 mPointerController->clearSpots();
6333 mPointerController->setButtonState(mCurrentRawState.buttonState);
6334 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
6335 } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
6336 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006337 }
Garfield Tan00f511d2019-06-12 16:55:40 -07006338 displayId = mPointerController->getDisplayId();
6339
6340 float xCursorPosition;
6341 float yCursorPosition;
6342 mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006343
6344 if (mPointerSimple.down && !down) {
6345 mPointerSimple.down = false;
6346
6347 // Send up.
Garfield Tan00f511d2019-06-12 16:55:40 -07006348 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6349 displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
6350 mLastRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006351 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
6352 &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
6353 xCursorPosition, yCursorPosition, mPointerSimple.downTime,
6354 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006355 getListener()->notifyMotion(&args);
6356 }
6357
6358 if (mPointerSimple.hovering && !hovering) {
6359 mPointerSimple.hovering = false;
6360
6361 // Send hover exit.
Garfield Tan00f511d2019-06-12 16:55:40 -07006362 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6363 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
6364 metaState, mLastRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006365 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
6366 &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
6367 xCursorPosition, yCursorPosition, mPointerSimple.downTime,
6368 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006369 getListener()->notifyMotion(&args);
6370 }
6371
6372 if (down) {
6373 if (!mPointerSimple.down) {
6374 mPointerSimple.down = true;
6375 mPointerSimple.downTime = when;
6376
6377 // Send down.
Garfield Tan00f511d2019-06-12 16:55:40 -07006378 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6379 displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
6380 metaState, mCurrentRawState.buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006381 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
6382 &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6383 mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
6384 yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006385 getListener()->notifyMotion(&args);
6386 }
6387
6388 // Send move.
Garfield Tan00f511d2019-06-12 16:55:40 -07006389 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6390 displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
6391 mCurrentRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006392 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
6393 &mPointerSimple.currentCoords, mOrientedXPrecision,
6394 mOrientedYPrecision, xCursorPosition, yCursorPosition,
6395 mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006396 getListener()->notifyMotion(&args);
6397 }
6398
6399 if (hovering) {
6400 if (!mPointerSimple.hovering) {
6401 mPointerSimple.hovering = true;
6402
6403 // Send hover enter.
Garfield Tan00f511d2019-06-12 16:55:40 -07006404 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6405 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
6406 metaState, mCurrentRawState.buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006407 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
6408 &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6409 mOrientedXPrecision, mOrientedYPrecision, xCursorPosition,
6410 yCursorPosition, mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006411 getListener()->notifyMotion(&args);
6412 }
6413
6414 // Send hover move.
Garfield Tan00f511d2019-06-12 16:55:40 -07006415 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6416 displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
6417 metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006418 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
6419 &mPointerSimple.currentCoords, mOrientedXPrecision,
6420 mOrientedYPrecision, xCursorPosition, yCursorPosition,
6421 mPointerSimple.downTime, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006422 getListener()->notifyMotion(&args);
6423 }
6424
Michael Wright842500e2015-03-13 17:32:02 -07006425 if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
6426 float vscroll = mCurrentRawState.rawVScroll;
6427 float hscroll = mCurrentRawState.rawHScroll;
Yi Kong9b14ac62018-07-17 13:48:38 -07006428 mWheelYVelocityControl.move(when, nullptr, &vscroll);
6429 mWheelXVelocityControl.move(when, &hscroll, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006430
6431 // Send scroll.
6432 PointerCoords pointerCoords;
6433 pointerCoords.copyFrom(mPointerSimple.currentCoords);
6434 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
6435 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
6436
Garfield Tan00f511d2019-06-12 16:55:40 -07006437 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
6438 displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
6439 mCurrentRawState.buttonState, MotionClassification::NONE,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006440 AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
6441 &pointerCoords, mOrientedXPrecision, mOrientedYPrecision,
6442 xCursorPosition, yCursorPosition, mPointerSimple.downTime,
6443 /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08006444 getListener()->notifyMotion(&args);
6445 }
6446
6447 // Save state.
6448 if (down || hovering) {
6449 mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
6450 mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
6451 } else {
6452 mPointerSimple.reset();
6453 }
6454}
6455
6456void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
6457 mPointerSimple.currentCoords.clear();
6458 mPointerSimple.currentProperties.clear();
6459
6460 dispatchPointerSimple(when, policyFlags, false, false);
6461}
6462
6463void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006464 int32_t action, int32_t actionButton, int32_t flags,
6465 int32_t metaState, int32_t buttonState, int32_t edgeFlags,
6466 const PointerProperties* properties,
6467 const PointerCoords* coords, const uint32_t* idToIndex,
6468 BitSet32 idBits, int32_t changedId, float xPrecision,
6469 float yPrecision, nsecs_t downTime) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006470 PointerCoords pointerCoords[MAX_POINTERS];
6471 PointerProperties pointerProperties[MAX_POINTERS];
6472 uint32_t pointerCount = 0;
6473 while (!idBits.isEmpty()) {
6474 uint32_t id = idBits.clearFirstMarkedBit();
6475 uint32_t index = idToIndex[id];
6476 pointerProperties[pointerCount].copyFrom(properties[index]);
6477 pointerCoords[pointerCount].copyFrom(coords[index]);
6478
6479 if (changedId >= 0 && id == uint32_t(changedId)) {
6480 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
6481 }
6482
6483 pointerCount += 1;
6484 }
6485
6486 ALOG_ASSERT(pointerCount != 0);
6487
6488 if (changedId >= 0 && pointerCount == 1) {
6489 // Replace initial down and final up action.
6490 // We can compare the action without masking off the changed pointer index
6491 // because we know the index is 0.
6492 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
6493 action = AMOTION_EVENT_ACTION_DOWN;
6494 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
6495 action = AMOTION_EVENT_ACTION_UP;
6496 } else {
6497 // Can't happen.
6498 ALOG_ASSERT(false);
6499 }
6500 }
Garfield Tan00f511d2019-06-12 16:55:40 -07006501 float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
6502 float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
6503 if (mDeviceMode == DEVICE_MODE_POINTER) {
6504 mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
6505 }
Arthur Hungc23540e2018-11-29 20:42:11 +08006506 const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
Siarhei Vishniakouadd89292018-12-13 19:23:36 -08006507 const int32_t deviceId = getDeviceId();
6508 std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
Siarhei Vishniakou8154bbd2019-02-15 17:21:03 -06006509 std::for_each(frames.begin(), frames.end(),
6510 [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
Garfield Tan00f511d2019-06-12 16:55:40 -07006511 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, source, displayId,
6512 policyFlags, action, actionButton, flags, metaState, buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07006513 MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
6514 pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
6515 downTime, std::move(frames));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006516 getListener()->notifyMotion(&args);
6517}
6518
6519bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
6520 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
6521 PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
6522 BitSet32 idBits) const {
6523 bool changed = false;
6524 while (!idBits.isEmpty()) {
6525 uint32_t id = idBits.clearFirstMarkedBit();
6526 uint32_t inIndex = inIdToIndex[id];
6527 uint32_t outIndex = outIdToIndex[id];
6528
6529 const PointerProperties& curInProperties = inProperties[inIndex];
6530 const PointerCoords& curInCoords = inCoords[inIndex];
6531 PointerProperties& curOutProperties = outProperties[outIndex];
6532 PointerCoords& curOutCoords = outCoords[outIndex];
6533
6534 if (curInProperties != curOutProperties) {
6535 curOutProperties.copyFrom(curInProperties);
6536 changed = true;
6537 }
6538
6539 if (curInCoords != curOutCoords) {
6540 curOutCoords.copyFrom(curInCoords);
6541 changed = true;
6542 }
6543 }
6544 return changed;
6545}
6546
6547void TouchInputMapper::fadePointer() {
Yi Kong9b14ac62018-07-17 13:48:38 -07006548 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006549 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
6550 }
6551}
6552
Jeff Brownc9aa6282015-02-11 19:03:28 -08006553void TouchInputMapper::cancelTouch(nsecs_t when) {
6554 abortPointerUsage(when, 0 /*policyFlags*/);
Michael Wright8e812822015-06-22 16:18:21 +01006555 abortTouches(when, 0 /* policyFlags*/);
Jeff Brownc9aa6282015-02-11 19:03:28 -08006556}
6557
Michael Wrightd02c5b62014-02-10 15:10:22 -08006558bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
Michael Wright358bcc72018-08-21 04:01:07 +01006559 const float scaledX = x * mXScale;
Michael Wrightc597d612018-08-22 13:49:32 +01006560 const float scaledY = y * mYScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006561 return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
Michael Wright358bcc72018-08-21 04:01:07 +01006562 && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
6563 && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
6564 && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006565}
6566
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006567const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006568
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006569 for (const VirtualKey& virtualKey: mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006570#if DEBUG_VIRTUAL_KEYS
6571 ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
6572 "left=%d, top=%d, right=%d, bottom=%d",
6573 x, y,
6574 virtualKey.keyCode, virtualKey.scanCode,
6575 virtualKey.hitLeft, virtualKey.hitTop,
6576 virtualKey.hitRight, virtualKey.hitBottom);
6577#endif
6578
6579 if (virtualKey.isHit(x, y)) {
6580 return & virtualKey;
6581 }
6582 }
6583
Yi Kong9b14ac62018-07-17 13:48:38 -07006584 return nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006585}
6586
Michael Wright842500e2015-03-13 17:32:02 -07006587void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
6588 uint32_t currentPointerCount = current->rawPointerData.pointerCount;
6589 uint32_t lastPointerCount = last->rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006590
Michael Wright842500e2015-03-13 17:32:02 -07006591 current->rawPointerData.clearIdBits();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006592
6593 if (currentPointerCount == 0) {
6594 // No pointers to assign.
6595 return;
6596 }
6597
6598 if (lastPointerCount == 0) {
6599 // All pointers are new.
6600 for (uint32_t i = 0; i < currentPointerCount; i++) {
6601 uint32_t id = i;
Michael Wright842500e2015-03-13 17:32:02 -07006602 current->rawPointerData.pointers[i].id = id;
6603 current->rawPointerData.idToIndex[id] = i;
6604 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006605 }
6606 return;
6607 }
6608
6609 if (currentPointerCount == 1 && lastPointerCount == 1
Michael Wright842500e2015-03-13 17:32:02 -07006610 && current->rawPointerData.pointers[0].toolType
6611 == last->rawPointerData.pointers[0].toolType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006612 // Only one pointer and no change in count so it must have the same id as before.
Michael Wright842500e2015-03-13 17:32:02 -07006613 uint32_t id = last->rawPointerData.pointers[0].id;
6614 current->rawPointerData.pointers[0].id = id;
6615 current->rawPointerData.idToIndex[id] = 0;
6616 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006617 return;
6618 }
6619
6620 // General case.
6621 // We build a heap of squared euclidean distances between current and last pointers
6622 // associated with the current and last pointer indices. Then, we find the best
6623 // match (by distance) for each current pointer.
6624 // The pointers must have the same tool type but it is possible for them to
6625 // transition from hovering to touching or vice-versa while retaining the same id.
6626 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
6627
6628 uint32_t heapSize = 0;
6629 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
6630 currentPointerIndex++) {
6631 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
6632 lastPointerIndex++) {
6633 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006634 current->rawPointerData.pointers[currentPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006635 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006636 last->rawPointerData.pointers[lastPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006637 if (currentPointer.toolType == lastPointer.toolType) {
6638 int64_t deltaX = currentPointer.x - lastPointer.x;
6639 int64_t deltaY = currentPointer.y - lastPointer.y;
6640
6641 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
6642
6643 // Insert new element into the heap (sift up).
6644 heap[heapSize].currentPointerIndex = currentPointerIndex;
6645 heap[heapSize].lastPointerIndex = lastPointerIndex;
6646 heap[heapSize].distance = distance;
6647 heapSize += 1;
6648 }
6649 }
6650 }
6651
6652 // Heapify
6653 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
6654 startIndex -= 1;
6655 for (uint32_t parentIndex = startIndex; ;) {
6656 uint32_t childIndex = parentIndex * 2 + 1;
6657 if (childIndex >= heapSize) {
6658 break;
6659 }
6660
6661 if (childIndex + 1 < heapSize
6662 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6663 childIndex += 1;
6664 }
6665
6666 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6667 break;
6668 }
6669
6670 swap(heap[parentIndex], heap[childIndex]);
6671 parentIndex = childIndex;
6672 }
6673 }
6674
6675#if DEBUG_POINTER_ASSIGNMENT
6676 ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
6677 for (size_t i = 0; i < heapSize; i++) {
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006678 ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006679 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6680 heap[i].distance);
6681 }
6682#endif
6683
6684 // Pull matches out by increasing order of distance.
6685 // To avoid reassigning pointers that have already been matched, the loop keeps track
6686 // of which last and current pointers have been matched using the matchedXXXBits variables.
6687 // It also tracks the used pointer id bits.
6688 BitSet32 matchedLastBits(0);
6689 BitSet32 matchedCurrentBits(0);
6690 BitSet32 usedIdBits(0);
6691 bool first = true;
6692 for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
6693 while (heapSize > 0) {
6694 if (first) {
6695 // The first time through the loop, we just consume the root element of
6696 // the heap (the one with smallest distance).
6697 first = false;
6698 } else {
6699 // Previous iterations consumed the root element of the heap.
6700 // Pop root element off of the heap (sift down).
6701 heap[0] = heap[heapSize];
6702 for (uint32_t parentIndex = 0; ;) {
6703 uint32_t childIndex = parentIndex * 2 + 1;
6704 if (childIndex >= heapSize) {
6705 break;
6706 }
6707
6708 if (childIndex + 1 < heapSize
6709 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6710 childIndex += 1;
6711 }
6712
6713 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6714 break;
6715 }
6716
6717 swap(heap[parentIndex], heap[childIndex]);
6718 parentIndex = childIndex;
6719 }
6720
6721#if DEBUG_POINTER_ASSIGNMENT
6722 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
6723 for (size_t i = 0; i < heapSize; i++) {
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006724 ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006725 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6726 heap[i].distance);
6727 }
6728#endif
6729 }
6730
6731 heapSize -= 1;
6732
6733 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
6734 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
6735
6736 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
6737 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
6738
6739 matchedCurrentBits.markBit(currentPointerIndex);
6740 matchedLastBits.markBit(lastPointerIndex);
6741
Michael Wright842500e2015-03-13 17:32:02 -07006742 uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
6743 current->rawPointerData.pointers[currentPointerIndex].id = id;
6744 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6745 current->rawPointerData.markIdBit(id,
6746 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006747 usedIdBits.markBit(id);
6748
6749#if DEBUG_POINTER_ASSIGNMENT
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006750 ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
6751 ", id=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006752 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
6753#endif
6754 break;
6755 }
6756 }
6757
6758 // Assign fresh ids to pointers that were not matched in the process.
6759 for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
6760 uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
6761 uint32_t id = usedIdBits.markFirstUnmarkedBit();
6762
Michael Wright842500e2015-03-13 17:32:02 -07006763 current->rawPointerData.pointers[currentPointerIndex].id = id;
6764 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6765 current->rawPointerData.markIdBit(id,
6766 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006767
6768#if DEBUG_POINTER_ASSIGNMENT
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006769 ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006770#endif
6771 }
6772}
6773
6774int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
6775 if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
6776 return AKEY_STATE_VIRTUAL;
6777 }
6778
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006779 for (const VirtualKey& virtualKey : mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006780 if (virtualKey.keyCode == keyCode) {
6781 return AKEY_STATE_UP;
6782 }
6783 }
6784
6785 return AKEY_STATE_UNKNOWN;
6786}
6787
6788int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
6789 if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
6790 return AKEY_STATE_VIRTUAL;
6791 }
6792
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006793 for (const VirtualKey& virtualKey : mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006794 if (virtualKey.scanCode == scanCode) {
6795 return AKEY_STATE_UP;
6796 }
6797 }
6798
6799 return AKEY_STATE_UNKNOWN;
6800}
6801
6802bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
6803 const int32_t* keyCodes, uint8_t* outFlags) {
Arthur Hung7c3ae9c2019-03-11 11:23:03 +08006804 for (const VirtualKey& virtualKey : mVirtualKeys) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006805 for (size_t i = 0; i < numCodes; i++) {
6806 if (virtualKey.keyCode == keyCodes[i]) {
6807 outFlags[i] = 1;
6808 }
6809 }
6810 }
6811
6812 return true;
6813}
6814
Arthur Hungc23540e2018-11-29 20:42:11 +08006815std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
6816 if (mParameters.hasAssociatedDisplay) {
6817 if (mDeviceMode == DEVICE_MODE_POINTER) {
6818 return std::make_optional(mPointerController->getDisplayId());
6819 } else {
6820 return std::make_optional(mViewport.displayId);
6821 }
6822 }
6823 return std::nullopt;
6824}
Michael Wrightd02c5b62014-02-10 15:10:22 -08006825
6826// --- SingleTouchInputMapper ---
6827
6828SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
6829 TouchInputMapper(device) {
6830}
6831
6832SingleTouchInputMapper::~SingleTouchInputMapper() {
6833}
6834
6835void SingleTouchInputMapper::reset(nsecs_t when) {
6836 mSingleTouchMotionAccumulator.reset(getDevice());
6837
6838 TouchInputMapper::reset(when);
6839}
6840
6841void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
6842 TouchInputMapper::process(rawEvent);
6843
6844 mSingleTouchMotionAccumulator.process(rawEvent);
6845}
6846
Michael Wright842500e2015-03-13 17:32:02 -07006847void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006848 if (mTouchButtonAccumulator.isToolActive()) {
Michael Wright842500e2015-03-13 17:32:02 -07006849 outState->rawPointerData.pointerCount = 1;
6850 outState->rawPointerData.idToIndex[0] = 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006851
6852 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6853 && (mTouchButtonAccumulator.isHovering()
6854 || (mRawPointerAxes.pressure.valid
6855 && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
Michael Wright842500e2015-03-13 17:32:02 -07006856 outState->rawPointerData.markIdBit(0, isHovering);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006857
Michael Wright842500e2015-03-13 17:32:02 -07006858 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006859 outPointer.id = 0;
6860 outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
6861 outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
6862 outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
6863 outPointer.touchMajor = 0;
6864 outPointer.touchMinor = 0;
6865 outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6866 outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6867 outPointer.orientation = 0;
6868 outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
6869 outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
6870 outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
6871 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6872 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6873 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6874 }
6875 outPointer.isHovering = isHovering;
6876 }
6877}
6878
6879void SingleTouchInputMapper::configureRawPointerAxes() {
6880 TouchInputMapper::configureRawPointerAxes();
6881
6882 getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
6883 getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
6884 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
6885 getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
6886 getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
6887 getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
6888 getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
6889}
6890
6891bool SingleTouchInputMapper::hasStylus() const {
6892 return mTouchButtonAccumulator.hasStylus();
6893}
6894
6895
6896// --- MultiTouchInputMapper ---
6897
6898MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
6899 TouchInputMapper(device) {
6900}
6901
6902MultiTouchInputMapper::~MultiTouchInputMapper() {
6903}
6904
6905void MultiTouchInputMapper::reset(nsecs_t when) {
6906 mMultiTouchMotionAccumulator.reset(getDevice());
6907
6908 mPointerIdBits.clear();
6909
6910 TouchInputMapper::reset(when);
6911}
6912
6913void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
6914 TouchInputMapper::process(rawEvent);
6915
6916 mMultiTouchMotionAccumulator.process(rawEvent);
6917}
6918
Michael Wright842500e2015-03-13 17:32:02 -07006919void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006920 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
6921 size_t outCount = 0;
6922 BitSet32 newPointerIdBits;
gaoshang1a632de2016-08-24 10:23:50 +08006923 mHavePointerIds = true;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006924
6925 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
6926 const MultiTouchMotionAccumulator::Slot* inSlot =
6927 mMultiTouchMotionAccumulator.getSlot(inIndex);
6928 if (!inSlot->isInUse()) {
6929 continue;
6930 }
6931
6932 if (outCount >= MAX_POINTERS) {
6933#if DEBUG_POINTERS
6934 ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
6935 "ignoring the rest.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01006936 getDeviceName().c_str(), MAX_POINTERS);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006937#endif
6938 break; // too many fingers!
6939 }
6940
Michael Wright842500e2015-03-13 17:32:02 -07006941 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006942 outPointer.x = inSlot->getX();
6943 outPointer.y = inSlot->getY();
6944 outPointer.pressure = inSlot->getPressure();
6945 outPointer.touchMajor = inSlot->getTouchMajor();
6946 outPointer.touchMinor = inSlot->getTouchMinor();
6947 outPointer.toolMajor = inSlot->getToolMajor();
6948 outPointer.toolMinor = inSlot->getToolMinor();
6949 outPointer.orientation = inSlot->getOrientation();
6950 outPointer.distance = inSlot->getDistance();
6951 outPointer.tiltX = 0;
6952 outPointer.tiltY = 0;
6953
6954 outPointer.toolType = inSlot->getToolType();
6955 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6956 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6957 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6958 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6959 }
6960 }
6961
6962 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6963 && (mTouchButtonAccumulator.isHovering()
6964 || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
6965 outPointer.isHovering = isHovering;
6966
6967 // Assign pointer id using tracking id if available.
gaoshang1a632de2016-08-24 10:23:50 +08006968 if (mHavePointerIds) {
6969 int32_t trackingId = inSlot->getTrackingId();
6970 int32_t id = -1;
6971 if (trackingId >= 0) {
6972 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
6973 uint32_t n = idBits.clearFirstMarkedBit();
6974 if (mPointerTrackingIdMap[n] == trackingId) {
6975 id = n;
6976 }
6977 }
6978
6979 if (id < 0 && !mPointerIdBits.isFull()) {
6980 id = mPointerIdBits.markFirstUnmarkedBit();
6981 mPointerTrackingIdMap[id] = trackingId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006982 }
Michael Wright842500e2015-03-13 17:32:02 -07006983 }
gaoshang1a632de2016-08-24 10:23:50 +08006984 if (id < 0) {
6985 mHavePointerIds = false;
6986 outState->rawPointerData.clearIdBits();
6987 newPointerIdBits.clear();
6988 } else {
6989 outPointer.id = id;
6990 outState->rawPointerData.idToIndex[id] = outCount;
6991 outState->rawPointerData.markIdBit(id, isHovering);
6992 newPointerIdBits.markBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006993 }
Michael Wright842500e2015-03-13 17:32:02 -07006994 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08006995 outCount += 1;
6996 }
6997
Michael Wright842500e2015-03-13 17:32:02 -07006998 outState->rawPointerData.pointerCount = outCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006999 mPointerIdBits = newPointerIdBits;
7000
7001 mMultiTouchMotionAccumulator.finishSync();
7002}
7003
7004void MultiTouchInputMapper::configureRawPointerAxes() {
7005 TouchInputMapper::configureRawPointerAxes();
7006
7007 getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
7008 getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
7009 getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
7010 getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
7011 getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
7012 getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
7013 getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
7014 getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
7015 getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
7016 getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
7017 getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
7018
7019 if (mRawPointerAxes.trackingId.valid
7020 && mRawPointerAxes.slot.valid
7021 && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
7022 size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
7023 if (slotCount > MAX_SLOTS) {
Narayan Kamath37764c72014-03-27 14:21:09 +00007024 ALOGW("MultiTouch Device %s reported %zu slots but the framework "
7025 "only supports a maximum of %zu slots at this time.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007026 getDeviceName().c_str(), slotCount, MAX_SLOTS);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007027 slotCount = MAX_SLOTS;
7028 }
7029 mMultiTouchMotionAccumulator.configure(getDevice(),
7030 slotCount, true /*usingSlotsProtocol*/);
7031 } else {
7032 mMultiTouchMotionAccumulator.configure(getDevice(),
7033 MAX_POINTERS, false /*usingSlotsProtocol*/);
7034 }
7035}
7036
7037bool MultiTouchInputMapper::hasStylus() const {
7038 return mMultiTouchMotionAccumulator.hasStylus()
7039 || mTouchButtonAccumulator.hasStylus();
7040}
7041
Michael Wright842500e2015-03-13 17:32:02 -07007042// --- ExternalStylusInputMapper
7043
7044ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
7045 InputMapper(device) {
7046
7047}
7048
7049uint32_t ExternalStylusInputMapper::getSources() {
7050 return AINPUT_SOURCE_STYLUS;
7051}
7052
7053void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
7054 InputMapper::populateDeviceInfo(info);
7055 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
7056 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
7057}
7058
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007059void ExternalStylusInputMapper::dump(std::string& dump) {
7060 dump += INDENT2 "External Stylus Input Mapper:\n";
7061 dump += INDENT3 "Raw Stylus Axes:\n";
Michael Wright842500e2015-03-13 17:32:02 -07007062 dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007063 dump += INDENT3 "Stylus State:\n";
Michael Wright842500e2015-03-13 17:32:02 -07007064 dumpStylusState(dump, mStylusState);
7065}
7066
7067void ExternalStylusInputMapper::configure(nsecs_t when,
7068 const InputReaderConfiguration* config, uint32_t changes) {
7069 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
7070 mTouchButtonAccumulator.configure(getDevice());
7071}
7072
7073void ExternalStylusInputMapper::reset(nsecs_t when) {
7074 InputDevice* device = getDevice();
7075 mSingleTouchMotionAccumulator.reset(device);
7076 mTouchButtonAccumulator.reset(device);
7077 InputMapper::reset(when);
7078}
7079
7080void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
7081 mSingleTouchMotionAccumulator.process(rawEvent);
7082 mTouchButtonAccumulator.process(rawEvent);
7083
7084 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
7085 sync(rawEvent->when);
7086 }
7087}
7088
7089void ExternalStylusInputMapper::sync(nsecs_t when) {
7090 mStylusState.clear();
7091
7092 mStylusState.when = when;
7093
Michael Wright45ccacf2015-04-21 19:01:58 +01007094 mStylusState.toolType = mTouchButtonAccumulator.getToolType();
7095 if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
7096 mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
7097 }
7098
Michael Wright842500e2015-03-13 17:32:02 -07007099 int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
7100 if (mRawPressureAxis.valid) {
7101 mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
7102 } else if (mTouchButtonAccumulator.isToolActive()) {
7103 mStylusState.pressure = 1.0f;
7104 } else {
7105 mStylusState.pressure = 0.0f;
7106 }
7107
7108 mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
Michael Wright842500e2015-03-13 17:32:02 -07007109
7110 mContext->dispatchExternalStylusState(mStylusState);
7111}
7112
Michael Wrightd02c5b62014-02-10 15:10:22 -08007113
7114// --- JoystickInputMapper ---
7115
7116JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
7117 InputMapper(device) {
7118}
7119
7120JoystickInputMapper::~JoystickInputMapper() {
7121}
7122
7123uint32_t JoystickInputMapper::getSources() {
7124 return AINPUT_SOURCE_JOYSTICK;
7125}
7126
7127void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
7128 InputMapper::populateDeviceInfo(info);
7129
7130 for (size_t i = 0; i < mAxes.size(); i++) {
7131 const Axis& axis = mAxes.valueAt(i);
7132 addMotionRange(axis.axisInfo.axis, axis, info);
7133
7134 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7135 addMotionRange(axis.axisInfo.highAxis, axis, info);
7136
7137 }
7138 }
7139}
7140
7141void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
7142 InputDeviceInfo* info) {
7143 info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
7144 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
7145 /* In order to ease the transition for developers from using the old axes
7146 * to the newer, more semantically correct axes, we'll continue to register
7147 * the old axes as duplicates of their corresponding new ones. */
7148 int32_t compatAxis = getCompatAxis(axisId);
7149 if (compatAxis >= 0) {
7150 info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
7151 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
7152 }
7153}
7154
7155/* A mapping from axes the joystick actually has to the axes that should be
7156 * artificially created for compatibility purposes.
7157 * Returns -1 if no compatibility axis is needed. */
7158int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
7159 switch(axis) {
7160 case AMOTION_EVENT_AXIS_LTRIGGER:
7161 return AMOTION_EVENT_AXIS_BRAKE;
7162 case AMOTION_EVENT_AXIS_RTRIGGER:
7163 return AMOTION_EVENT_AXIS_GAS;
7164 }
7165 return -1;
7166}
7167
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007168void JoystickInputMapper::dump(std::string& dump) {
7169 dump += INDENT2 "Joystick Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007170
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007171 dump += INDENT3 "Axes:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007172 size_t numAxes = mAxes.size();
7173 for (size_t i = 0; i < numAxes; i++) {
7174 const Axis& axis = mAxes.valueAt(i);
7175 const char* label = getAxisLabel(axis.axisInfo.axis);
7176 if (label) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007177 dump += StringPrintf(INDENT4 "%s", label);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007178 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007179 dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007180 }
7181 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7182 label = getAxisLabel(axis.axisInfo.highAxis);
7183 if (label) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007184 dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007185 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007186 dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
Michael Wrightd02c5b62014-02-10 15:10:22 -08007187 axis.axisInfo.splitValue);
7188 }
7189 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007190 dump += " (invert)";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007191 }
7192
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007193 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 -08007194 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007195 dump += StringPrintf(INDENT4 " scale=%0.5f, offset=%0.5f, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08007196 "highScale=%0.5f, highOffset=%0.5f\n",
7197 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007198 dump += StringPrintf(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08007199 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
7200 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
7201 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
7202 }
7203}
7204
7205void JoystickInputMapper::configure(nsecs_t when,
7206 const InputReaderConfiguration* config, uint32_t changes) {
7207 InputMapper::configure(when, config, changes);
7208
7209 if (!changes) { // first time only
7210 // Collect all axes.
7211 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
7212 if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
7213 & INPUT_DEVICE_CLASS_JOYSTICK)) {
7214 continue; // axis must be claimed by a different device
7215 }
7216
7217 RawAbsoluteAxisInfo rawAxisInfo;
7218 getAbsoluteAxisInfo(abs, &rawAxisInfo);
7219 if (rawAxisInfo.valid) {
7220 // Map axis.
7221 AxisInfo axisInfo;
7222 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
7223 if (!explicitlyMapped) {
7224 // Axis is not explicitly mapped, will choose a generic axis later.
7225 axisInfo.mode = AxisInfo::MODE_NORMAL;
7226 axisInfo.axis = -1;
7227 }
7228
7229 // Apply flat override.
7230 int32_t rawFlat = axisInfo.flatOverride < 0
7231 ? rawAxisInfo.flat : axisInfo.flatOverride;
7232
7233 // Calculate scaling factors and limits.
7234 Axis axis;
7235 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
7236 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
7237 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
7238 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7239 scale, 0.0f, highScale, 0.0f,
7240 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7241 rawAxisInfo.resolution * scale);
7242 } else if (isCenteredAxis(axisInfo.axis)) {
7243 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
7244 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
7245 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7246 scale, offset, scale, offset,
7247 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7248 rawAxisInfo.resolution * scale);
7249 } else {
7250 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
7251 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7252 scale, 0.0f, scale, 0.0f,
7253 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7254 rawAxisInfo.resolution * scale);
7255 }
7256
7257 // To eliminate noise while the joystick is at rest, filter out small variations
7258 // in axis values up front.
7259 axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
7260
7261 mAxes.add(abs, axis);
7262 }
7263 }
7264
7265 // If there are too many axes, start dropping them.
7266 // Prefer to keep explicitly mapped axes.
7267 if (mAxes.size() > PointerCoords::MAX_AXES) {
Narayan Kamath37764c72014-03-27 14:21:09 +00007268 ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007269 getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007270 pruneAxes(true);
7271 pruneAxes(false);
7272 }
7273
7274 // Assign generic axis ids to remaining axes.
7275 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
7276 size_t numAxes = mAxes.size();
7277 for (size_t i = 0; i < numAxes; i++) {
7278 Axis& axis = mAxes.editValueAt(i);
7279 if (axis.axisInfo.axis < 0) {
7280 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
7281 && haveAxis(nextGenericAxisId)) {
7282 nextGenericAxisId += 1;
7283 }
7284
7285 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
7286 axis.axisInfo.axis = nextGenericAxisId;
7287 nextGenericAxisId += 1;
7288 } else {
7289 ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
7290 "have already been assigned to other axes.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007291 getDeviceName().c_str(), mAxes.keyAt(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08007292 mAxes.removeItemsAt(i--);
7293 numAxes -= 1;
7294 }
7295 }
7296 }
7297 }
7298}
7299
7300bool JoystickInputMapper::haveAxis(int32_t axisId) {
7301 size_t numAxes = mAxes.size();
7302 for (size_t i = 0; i < numAxes; i++) {
7303 const Axis& axis = mAxes.valueAt(i);
7304 if (axis.axisInfo.axis == axisId
7305 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
7306 && axis.axisInfo.highAxis == axisId)) {
7307 return true;
7308 }
7309 }
7310 return false;
7311}
7312
7313void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
7314 size_t i = mAxes.size();
7315 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
7316 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
7317 continue;
7318 }
7319 ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007320 getDeviceName().c_str(), mAxes.keyAt(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08007321 mAxes.removeItemsAt(i);
7322 }
7323}
7324
7325bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
7326 switch (axis) {
7327 case AMOTION_EVENT_AXIS_X:
7328 case AMOTION_EVENT_AXIS_Y:
7329 case AMOTION_EVENT_AXIS_Z:
7330 case AMOTION_EVENT_AXIS_RX:
7331 case AMOTION_EVENT_AXIS_RY:
7332 case AMOTION_EVENT_AXIS_RZ:
7333 case AMOTION_EVENT_AXIS_HAT_X:
7334 case AMOTION_EVENT_AXIS_HAT_Y:
7335 case AMOTION_EVENT_AXIS_ORIENTATION:
7336 case AMOTION_EVENT_AXIS_RUDDER:
7337 case AMOTION_EVENT_AXIS_WHEEL:
7338 return true;
7339 default:
7340 return false;
7341 }
7342}
7343
7344void JoystickInputMapper::reset(nsecs_t when) {
7345 // Recenter all axes.
7346 size_t numAxes = mAxes.size();
7347 for (size_t i = 0; i < numAxes; i++) {
7348 Axis& axis = mAxes.editValueAt(i);
7349 axis.resetValue();
7350 }
7351
7352 InputMapper::reset(when);
7353}
7354
7355void JoystickInputMapper::process(const RawEvent* rawEvent) {
7356 switch (rawEvent->type) {
7357 case EV_ABS: {
7358 ssize_t index = mAxes.indexOfKey(rawEvent->code);
7359 if (index >= 0) {
7360 Axis& axis = mAxes.editValueAt(index);
7361 float newValue, highNewValue;
7362 switch (axis.axisInfo.mode) {
7363 case AxisInfo::MODE_INVERT:
7364 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
7365 * axis.scale + axis.offset;
7366 highNewValue = 0.0f;
7367 break;
7368 case AxisInfo::MODE_SPLIT:
7369 if (rawEvent->value < axis.axisInfo.splitValue) {
7370 newValue = (axis.axisInfo.splitValue - rawEvent->value)
7371 * axis.scale + axis.offset;
7372 highNewValue = 0.0f;
7373 } else if (rawEvent->value > axis.axisInfo.splitValue) {
7374 newValue = 0.0f;
7375 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
7376 * axis.highScale + axis.highOffset;
7377 } else {
7378 newValue = 0.0f;
7379 highNewValue = 0.0f;
7380 }
7381 break;
7382 default:
7383 newValue = rawEvent->value * axis.scale + axis.offset;
7384 highNewValue = 0.0f;
7385 break;
7386 }
7387 axis.newValue = newValue;
7388 axis.highNewValue = highNewValue;
7389 }
7390 break;
7391 }
7392
7393 case EV_SYN:
7394 switch (rawEvent->code) {
7395 case SYN_REPORT:
7396 sync(rawEvent->when, false /*force*/);
7397 break;
7398 }
7399 break;
7400 }
7401}
7402
7403void JoystickInputMapper::sync(nsecs_t when, bool force) {
7404 if (!filterAxes(force)) {
7405 return;
7406 }
7407
7408 int32_t metaState = mContext->getGlobalMetaState();
7409 int32_t buttonState = 0;
7410
7411 PointerProperties pointerProperties;
7412 pointerProperties.clear();
7413 pointerProperties.id = 0;
7414 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
7415
7416 PointerCoords pointerCoords;
7417 pointerCoords.clear();
7418
7419 size_t numAxes = mAxes.size();
7420 for (size_t i = 0; i < numAxes; i++) {
7421 const Axis& axis = mAxes.valueAt(i);
7422 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
7423 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7424 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
7425 axis.highCurrentValue);
7426 }
7427 }
7428
7429 // Moving a joystick axis should not wake the device because joysticks can
7430 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
7431 // button will likely wake the device.
7432 // TODO: Use the input device configuration to control this behavior more finely.
7433 uint32_t policyFlags = 0;
7434
Prabir Pradhan42611e02018-11-27 14:04:02 -08007435 NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
Garfield Tan00f511d2019-06-12 16:55:40 -07007436 AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
7437 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
Atif Niyaz21da0ff2019-06-28 13:22:51 -07007438 MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
7439 &pointerProperties, &pointerCoords, 0, 0,
Garfield Tan00f511d2019-06-12 16:55:40 -07007440 AMOTION_EVENT_INVALID_CURSOR_POSITION,
7441 AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
Michael Wrightd02c5b62014-02-10 15:10:22 -08007442 getListener()->notifyMotion(&args);
7443}
7444
7445void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
7446 int32_t axis, float value) {
7447 pointerCoords->setAxisValue(axis, value);
7448 /* In order to ease the transition for developers from using the old axes
7449 * to the newer, more semantically correct axes, we'll continue to produce
7450 * values for the old axes as mirrors of the value of their corresponding
7451 * new axes. */
7452 int32_t compatAxis = getCompatAxis(axis);
7453 if (compatAxis >= 0) {
7454 pointerCoords->setAxisValue(compatAxis, value);
7455 }
7456}
7457
7458bool JoystickInputMapper::filterAxes(bool force) {
7459 bool atLeastOneSignificantChange = force;
7460 size_t numAxes = mAxes.size();
7461 for (size_t i = 0; i < numAxes; i++) {
7462 Axis& axis = mAxes.editValueAt(i);
7463 if (force || hasValueChangedSignificantly(axis.filter,
7464 axis.newValue, axis.currentValue, axis.min, axis.max)) {
7465 axis.currentValue = axis.newValue;
7466 atLeastOneSignificantChange = true;
7467 }
7468 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7469 if (force || hasValueChangedSignificantly(axis.filter,
7470 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
7471 axis.highCurrentValue = axis.highNewValue;
7472 atLeastOneSignificantChange = true;
7473 }
7474 }
7475 }
7476 return atLeastOneSignificantChange;
7477}
7478
7479bool JoystickInputMapper::hasValueChangedSignificantly(
7480 float filter, float newValue, float currentValue, float min, float max) {
7481 if (newValue != currentValue) {
7482 // Filter out small changes in value unless the value is converging on the axis
7483 // bounds or center point. This is intended to reduce the amount of information
7484 // sent to applications by particularly noisy joysticks (such as PS3).
7485 if (fabs(newValue - currentValue) > filter
7486 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
7487 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
7488 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
7489 return true;
7490 }
7491 }
7492 return false;
7493}
7494
7495bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
7496 float filter, float newValue, float currentValue, float thresholdValue) {
7497 float newDistance = fabs(newValue - thresholdValue);
7498 if (newDistance < filter) {
7499 float oldDistance = fabs(currentValue - thresholdValue);
7500 if (newDistance < oldDistance) {
7501 return true;
7502 }
7503 }
7504 return false;
7505}
7506
7507} // namespace android