blob: 57fc17fb5037d12daf8637fe610ddb3032cbe610 [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.
74static const size_t MAX_SLOTS = 32;
75
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.
Michael Wright5e17a5d2015-04-21 22:45:13 +010078static const 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.
81static const nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20);
82
83// Artificial latency on synthetic events created from stylus data without corresponding touch
84// data.
85static const 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))) {
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +0100239 NotifyKeyArgs args(when, deviceId, source, displayId, policyFlags,
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240 action, 0, keyCode, 0, context->getGlobalMetaState(), when);
241 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
257// --- InputReaderConfiguration ---
258
Santos Cordonfa5cf462017-04-05 10:37:00 -0700259bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100260 const std::string& uniqueDisplayId, DisplayViewport* outViewport) const {
Siarhei Vishniakoud6343922018-07-06 23:33:37 +0100261 for (const DisplayViewport& currentViewport : mDisplays) {
Siarhei Vishniakou2d0867f2018-08-08 17:57:57 -0700262 if (currentViewport.type == viewportType) {
263 if (uniqueDisplayId.empty() ||
264 (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) {
Siarhei Vishniakoud6343922018-07-06 23:33:37 +0100265 *outViewport = currentViewport;
266 return true;
Santos Cordonfa5cf462017-04-05 10:37:00 -0700267 }
268 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800269 }
270 return false;
271}
272
Siarhei Vishniakoud6343922018-07-06 23:33:37 +0100273void InputReaderConfiguration::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
274 mDisplays = viewports;
Santos Cordonfa5cf462017-04-05 10:37:00 -0700275}
276
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800277void InputReaderConfiguration::dump(std::string& dump) const {
Siarhei Vishniakoud6343922018-07-06 23:33:37 +0100278 for (const DisplayViewport& viewport : mDisplays) {
Santos Cordonfa5cf462017-04-05 10:37:00 -0700279 dumpViewport(dump, viewport);
280 }
281}
282
Siarhei Vishniakoud6343922018-07-06 23:33:37 +0100283void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport)
284 const {
285 dump += StringPrintf(INDENT4 "%s\n", viewport.toString().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800286}
287
288
Jason Gereckeaf126fb2012-05-10 14:22:47 -0700289// -- TouchAffineTransformation --
290void TouchAffineTransformation::applyTo(float& x, float& y) const {
291 float newX, newY;
292 newX = x * x_scale + y * x_ymix + x_offset;
293 newY = x * y_xmix + y * y_scale + y_offset;
294
295 x = newX;
296 y = newY;
297}
298
299
Michael Wrightd02c5b62014-02-10 15:10:22 -0800300// --- InputReader ---
301
302InputReader::InputReader(const sp<EventHubInterface>& eventHub,
303 const sp<InputReaderPolicyInterface>& policy,
304 const sp<InputListenerInterface>& listener) :
305 mContext(this), mEventHub(eventHub), mPolicy(policy),
306 mGlobalMetaState(0), mGeneration(1),
307 mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
308 mConfigurationChangesToRefresh(0) {
309 mQueuedListener = new QueuedInputListener(listener);
310
311 { // acquire lock
312 AutoMutex _l(mLock);
313
314 refreshConfigurationLocked(0);
315 updateGlobalMetaStateLocked();
316 } // release lock
317}
318
319InputReader::~InputReader() {
320 for (size_t i = 0; i < mDevices.size(); i++) {
321 delete mDevices.valueAt(i);
322 }
323}
324
325void InputReader::loopOnce() {
326 int32_t oldGeneration;
327 int32_t timeoutMillis;
328 bool inputDevicesChanged = false;
329 Vector<InputDeviceInfo> inputDevices;
330 { // acquire lock
331 AutoMutex _l(mLock);
332
333 oldGeneration = mGeneration;
334 timeoutMillis = -1;
335
336 uint32_t changes = mConfigurationChangesToRefresh;
337 if (changes) {
338 mConfigurationChangesToRefresh = 0;
339 timeoutMillis = 0;
340 refreshConfigurationLocked(changes);
341 } else if (mNextTimeout != LLONG_MAX) {
342 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
343 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
344 }
345 } // release lock
346
347 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
348
349 { // acquire lock
350 AutoMutex _l(mLock);
351 mReaderIsAliveCondition.broadcast();
352
353 if (count) {
354 processEventsLocked(mEventBuffer, count);
355 }
356
357 if (mNextTimeout != LLONG_MAX) {
358 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
359 if (now >= mNextTimeout) {
360#if DEBUG_RAW_EVENTS
361 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
362#endif
363 mNextTimeout = LLONG_MAX;
364 timeoutExpiredLocked(now);
365 }
366 }
367
368 if (oldGeneration != mGeneration) {
369 inputDevicesChanged = true;
370 getInputDevicesLocked(inputDevices);
371 }
372 } // release lock
373
374 // Send out a message that the describes the changed input devices.
375 if (inputDevicesChanged) {
376 mPolicy->notifyInputDevicesChanged(inputDevices);
377 }
378
379 // Flush queued events out to the listener.
380 // This must happen outside of the lock because the listener could potentially call
381 // back into the InputReader's methods, such as getScanCodeState, or become blocked
382 // on another thread similarly waiting to acquire the InputReader lock thereby
383 // resulting in a deadlock. This situation is actually quite plausible because the
384 // listener is actually the input dispatcher, which calls into the window manager,
385 // which occasionally calls into the input reader.
386 mQueuedListener->flush();
387}
388
389void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
390 for (const RawEvent* rawEvent = rawEvents; count;) {
391 int32_t type = rawEvent->type;
392 size_t batchSize = 1;
393 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
394 int32_t deviceId = rawEvent->deviceId;
395 while (batchSize < count) {
396 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
397 || rawEvent[batchSize].deviceId != deviceId) {
398 break;
399 }
400 batchSize += 1;
401 }
402#if DEBUG_RAW_EVENTS
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -0700403 ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800404#endif
405 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
406 } else {
407 switch (rawEvent->type) {
408 case EventHubInterface::DEVICE_ADDED:
409 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
410 break;
411 case EventHubInterface::DEVICE_REMOVED:
412 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
413 break;
414 case EventHubInterface::FINISHED_DEVICE_SCAN:
415 handleConfigurationChangedLocked(rawEvent->when);
416 break;
417 default:
418 ALOG_ASSERT(false); // can't happen
419 break;
420 }
421 }
422 count -= batchSize;
423 rawEvent += batchSize;
424 }
425}
426
427void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
428 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
429 if (deviceIndex >= 0) {
430 ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
431 return;
432 }
433
434 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
435 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
436 int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
437
438 InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
439 device->configure(when, &mConfig, 0);
440 device->reset(when);
441
442 if (device->isIgnored()) {
443 ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100444 identifier.name.c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800445 } else {
446 ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100447 identifier.name.c_str(), device->getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800448 }
449
450 mDevices.add(deviceId, device);
451 bumpGenerationLocked();
Michael Wright842500e2015-03-13 17:32:02 -0700452
453 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
454 notifyExternalStylusPresenceChanged();
455 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800456}
457
458void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
Yi Kong9b14ac62018-07-17 13:48:38 -0700459 InputDevice* device = nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800460 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
461 if (deviceIndex < 0) {
462 ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
463 return;
464 }
465
466 device = mDevices.valueAt(deviceIndex);
467 mDevices.removeItemsAt(deviceIndex, 1);
468 bumpGenerationLocked();
469
470 if (device->isIgnored()) {
471 ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100472 device->getId(), device->getName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800473 } else {
474 ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100475 device->getId(), device->getName().c_str(), device->getSources());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800476 }
477
Michael Wright842500e2015-03-13 17:32:02 -0700478 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
479 notifyExternalStylusPresenceChanged();
480 }
481
Michael Wrightd02c5b62014-02-10 15:10:22 -0800482 device->reset(when);
483 delete device;
484}
485
486InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
487 const InputDeviceIdentifier& identifier, uint32_t classes) {
488 InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
489 controllerNumber, identifier, classes);
490
491 // External devices.
492 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
493 device->setExternal(true);
494 }
495
Tim Kilbourn063ff532015-04-08 10:26:18 -0700496 // Devices with mics.
497 if (classes & INPUT_DEVICE_CLASS_MIC) {
498 device->setMic(true);
499 }
500
Michael Wrightd02c5b62014-02-10 15:10:22 -0800501 // Switch-like devices.
502 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
503 device->addMapper(new SwitchInputMapper(device));
504 }
505
Prashant Malani1941ff52015-08-11 18:29:28 -0700506 // Scroll wheel-like devices.
507 if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
508 device->addMapper(new RotaryEncoderInputMapper(device));
509 }
510
Michael Wrightd02c5b62014-02-10 15:10:22 -0800511 // Vibrator-like devices.
512 if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
513 device->addMapper(new VibratorInputMapper(device));
514 }
515
516 // Keyboard-like devices.
517 uint32_t keyboardSource = 0;
518 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
519 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
520 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
521 }
522 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
523 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
524 }
525 if (classes & INPUT_DEVICE_CLASS_DPAD) {
526 keyboardSource |= AINPUT_SOURCE_DPAD;
527 }
528 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
529 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
530 }
531
532 if (keyboardSource != 0) {
533 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
534 }
535
536 // Cursor-like devices.
537 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
538 device->addMapper(new CursorInputMapper(device));
539 }
540
541 // Touchscreens and touchpad devices.
542 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
543 device->addMapper(new MultiTouchInputMapper(device));
544 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
545 device->addMapper(new SingleTouchInputMapper(device));
546 }
547
548 // Joystick-like devices.
549 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
550 device->addMapper(new JoystickInputMapper(device));
551 }
552
Michael Wright842500e2015-03-13 17:32:02 -0700553 // External stylus-like devices.
554 if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
555 device->addMapper(new ExternalStylusInputMapper(device));
556 }
557
Michael Wrightd02c5b62014-02-10 15:10:22 -0800558 return device;
559}
560
561void InputReader::processEventsForDeviceLocked(int32_t deviceId,
562 const RawEvent* rawEvents, size_t count) {
563 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
564 if (deviceIndex < 0) {
565 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
566 return;
567 }
568
569 InputDevice* device = mDevices.valueAt(deviceIndex);
570 if (device->isIgnored()) {
571 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
572 return;
573 }
574
575 device->process(rawEvents, count);
576}
577
578void InputReader::timeoutExpiredLocked(nsecs_t when) {
579 for (size_t i = 0; i < mDevices.size(); i++) {
580 InputDevice* device = mDevices.valueAt(i);
581 if (!device->isIgnored()) {
582 device->timeoutExpired(when);
583 }
584 }
585}
586
587void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
588 // Reset global meta state because it depends on the list of all configured devices.
589 updateGlobalMetaStateLocked();
590
591 // Enqueue configuration changed.
592 NotifyConfigurationChangedArgs args(when);
593 mQueuedListener->notifyConfigurationChanged(&args);
594}
595
596void InputReader::refreshConfigurationLocked(uint32_t changes) {
597 mPolicy->getReaderConfiguration(&mConfig);
598 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
599
600 if (changes) {
601 ALOGI("Reconfiguring input devices. changes=0x%08x", changes);
602 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
603
604 if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
605 mEventHub->requestReopenDevices();
606 } else {
607 for (size_t i = 0; i < mDevices.size(); i++) {
608 InputDevice* device = mDevices.valueAt(i);
609 device->configure(now, &mConfig, changes);
610 }
611 }
612 }
613}
614
615void InputReader::updateGlobalMetaStateLocked() {
616 mGlobalMetaState = 0;
617
618 for (size_t i = 0; i < mDevices.size(); i++) {
619 InputDevice* device = mDevices.valueAt(i);
620 mGlobalMetaState |= device->getMetaState();
621 }
622}
623
624int32_t InputReader::getGlobalMetaStateLocked() {
625 return mGlobalMetaState;
626}
627
Michael Wright842500e2015-03-13 17:32:02 -0700628void InputReader::notifyExternalStylusPresenceChanged() {
629 refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
630}
631
632void InputReader::getExternalStylusDevicesLocked(Vector<InputDeviceInfo>& outDevices) {
633 for (size_t i = 0; i < mDevices.size(); i++) {
634 InputDevice* device = mDevices.valueAt(i);
635 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
636 outDevices.push();
637 device->getDeviceInfo(&outDevices.editTop());
638 }
639 }
640}
641
642void InputReader::dispatchExternalStylusState(const StylusState& state) {
643 for (size_t i = 0; i < mDevices.size(); i++) {
644 InputDevice* device = mDevices.valueAt(i);
645 device->updateExternalStylusState(state);
646 }
647}
648
Michael Wrightd02c5b62014-02-10 15:10:22 -0800649void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
650 mDisableVirtualKeysTimeout = time;
651}
652
653bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
654 InputDevice* device, int32_t keyCode, int32_t scanCode) {
655 if (now < mDisableVirtualKeysTimeout) {
656 ALOGI("Dropping virtual key from device %s because virtual keys are "
657 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100658 device->getName().c_str(),
Michael Wrightd02c5b62014-02-10 15:10:22 -0800659 (mDisableVirtualKeysTimeout - now) * 0.000001,
660 keyCode, scanCode);
661 return true;
662 } else {
663 return false;
664 }
665}
666
667void InputReader::fadePointerLocked() {
668 for (size_t i = 0; i < mDevices.size(); i++) {
669 InputDevice* device = mDevices.valueAt(i);
670 device->fadePointer();
671 }
672}
673
674void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
675 if (when < mNextTimeout) {
676 mNextTimeout = when;
677 mEventHub->wake();
678 }
679}
680
681int32_t InputReader::bumpGenerationLocked() {
682 return ++mGeneration;
683}
684
685void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) {
686 AutoMutex _l(mLock);
687 getInputDevicesLocked(outInputDevices);
688}
689
690void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) {
691 outInputDevices.clear();
692
693 size_t numDevices = mDevices.size();
694 for (size_t i = 0; i < numDevices; i++) {
695 InputDevice* device = mDevices.valueAt(i);
696 if (!device->isIgnored()) {
697 outInputDevices.push();
698 device->getDeviceInfo(&outInputDevices.editTop());
699 }
700 }
701}
702
703int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
704 int32_t keyCode) {
705 AutoMutex _l(mLock);
706
707 return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
708}
709
710int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
711 int32_t scanCode) {
712 AutoMutex _l(mLock);
713
714 return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
715}
716
717int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
718 AutoMutex _l(mLock);
719
720 return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
721}
722
723int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
724 GetStateFunc getStateFunc) {
725 int32_t result = AKEY_STATE_UNKNOWN;
726 if (deviceId >= 0) {
727 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
728 if (deviceIndex >= 0) {
729 InputDevice* device = mDevices.valueAt(deviceIndex);
730 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
731 result = (device->*getStateFunc)(sourceMask, code);
732 }
733 }
734 } else {
735 size_t numDevices = mDevices.size();
736 for (size_t i = 0; i < numDevices; i++) {
737 InputDevice* device = mDevices.valueAt(i);
738 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
739 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
740 // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
741 int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
742 if (currentResult >= AKEY_STATE_DOWN) {
743 return currentResult;
744 } else if (currentResult == AKEY_STATE_UP) {
745 result = currentResult;
746 }
747 }
748 }
749 }
750 return result;
751}
752
Andrii Kulian763a3a42016-03-08 10:46:16 -0800753void InputReader::toggleCapsLockState(int32_t deviceId) {
754 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
755 if (deviceIndex < 0) {
756 ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
757 return;
758 }
759
760 InputDevice* device = mDevices.valueAt(deviceIndex);
761 if (device->isIgnored()) {
762 return;
763 }
764
765 device->updateMetaState(AKEYCODE_CAPS_LOCK);
766}
767
Michael Wrightd02c5b62014-02-10 15:10:22 -0800768bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
769 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
770 AutoMutex _l(mLock);
771
772 memset(outFlags, 0, numCodes);
773 return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
774}
775
776bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
777 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
778 bool result = false;
779 if (deviceId >= 0) {
780 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
781 if (deviceIndex >= 0) {
782 InputDevice* device = mDevices.valueAt(deviceIndex);
783 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
784 result = device->markSupportedKeyCodes(sourceMask,
785 numCodes, keyCodes, outFlags);
786 }
787 }
788 } else {
789 size_t numDevices = mDevices.size();
790 for (size_t i = 0; i < numDevices; i++) {
791 InputDevice* device = mDevices.valueAt(i);
792 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
793 result |= device->markSupportedKeyCodes(sourceMask,
794 numCodes, keyCodes, outFlags);
795 }
796 }
797 }
798 return result;
799}
800
801void InputReader::requestRefreshConfiguration(uint32_t changes) {
802 AutoMutex _l(mLock);
803
804 if (changes) {
805 bool needWake = !mConfigurationChangesToRefresh;
806 mConfigurationChangesToRefresh |= changes;
807
808 if (needWake) {
809 mEventHub->wake();
810 }
811 }
812}
813
814void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
815 ssize_t repeat, int32_t token) {
816 AutoMutex _l(mLock);
817
818 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
819 if (deviceIndex >= 0) {
820 InputDevice* device = mDevices.valueAt(deviceIndex);
821 device->vibrate(pattern, patternSize, repeat, token);
822 }
823}
824
825void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
826 AutoMutex _l(mLock);
827
828 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
829 if (deviceIndex >= 0) {
830 InputDevice* device = mDevices.valueAt(deviceIndex);
831 device->cancelVibrate(token);
832 }
833}
834
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -0700835bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
836 AutoMutex _l(mLock);
837
838 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
839 if (deviceIndex >= 0) {
840 InputDevice* device = mDevices.valueAt(deviceIndex);
841 return device->isEnabled();
842 }
843 ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
844 return false;
845}
846
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800847void InputReader::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800848 AutoMutex _l(mLock);
849
850 mEventHub->dump(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800851 dump += "\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800852
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800853 dump += "Input Reader State:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800854
855 for (size_t i = 0; i < mDevices.size(); i++) {
856 mDevices.valueAt(i)->dump(dump);
857 }
858
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800859 dump += INDENT "Configuration:\n";
860 dump += INDENT2 "ExcludedDeviceNames: [";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800861 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
862 if (i != 0) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800863 dump += ", ";
Michael Wrightd02c5b62014-02-10 15:10:22 -0800864 }
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100865 dump += mConfig.excludedDeviceNames[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -0800866 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800867 dump += "]\n";
868 dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800869 mConfig.virtualKeyQuietTime * 0.000001f);
870
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800871 dump += StringPrintf(INDENT2 "PointerVelocityControlParameters: "
Michael Wrightd02c5b62014-02-10 15:10:22 -0800872 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
873 mConfig.pointerVelocityControlParameters.scale,
874 mConfig.pointerVelocityControlParameters.lowThreshold,
875 mConfig.pointerVelocityControlParameters.highThreshold,
876 mConfig.pointerVelocityControlParameters.acceleration);
877
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800878 dump += StringPrintf(INDENT2 "WheelVelocityControlParameters: "
Michael Wrightd02c5b62014-02-10 15:10:22 -0800879 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
880 mConfig.wheelVelocityControlParameters.scale,
881 mConfig.wheelVelocityControlParameters.lowThreshold,
882 mConfig.wheelVelocityControlParameters.highThreshold,
883 mConfig.wheelVelocityControlParameters.acceleration);
884
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800885 dump += StringPrintf(INDENT2 "PointerGesture:\n");
886 dump += StringPrintf(INDENT3 "Enabled: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800887 toString(mConfig.pointerGesturesEnabled));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800888 dump += StringPrintf(INDENT3 "QuietInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800889 mConfig.pointerGestureQuietInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800890 dump += StringPrintf(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800891 mConfig.pointerGestureDragMinSwitchSpeed);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800892 dump += StringPrintf(INDENT3 "TapInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800893 mConfig.pointerGestureTapInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800894 dump += StringPrintf(INDENT3 "TapDragInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800895 mConfig.pointerGestureTapDragInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800896 dump += StringPrintf(INDENT3 "TapSlop: %0.1fpx\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800897 mConfig.pointerGestureTapSlop);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800898 dump += StringPrintf(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800899 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800900 dump += StringPrintf(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800901 mConfig.pointerGestureMultitouchMinDistance);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800902 dump += StringPrintf(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800903 mConfig.pointerGestureSwipeTransitionAngleCosine);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800904 dump += StringPrintf(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800905 mConfig.pointerGestureSwipeMaxWidthRatio);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800906 dump += StringPrintf(INDENT3 "MovementSpeedRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800907 mConfig.pointerGestureMovementSpeedRatio);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800908 dump += StringPrintf(INDENT3 "ZoomSpeedRatio: %0.1f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -0800909 mConfig.pointerGestureZoomSpeedRatio);
Santos Cordonfa5cf462017-04-05 10:37:00 -0700910
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -0800911 dump += INDENT3 "Viewports:\n";
Santos Cordonfa5cf462017-04-05 10:37:00 -0700912 mConfig.dump(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -0800913}
914
915void InputReader::monitor() {
916 // Acquire and release the lock to ensure that the reader has not deadlocked.
917 mLock.lock();
918 mEventHub->wake();
919 mReaderIsAliveCondition.wait(mLock);
920 mLock.unlock();
921
922 // Check the EventHub
923 mEventHub->monitor();
924}
925
926
927// --- InputReader::ContextImpl ---
928
929InputReader::ContextImpl::ContextImpl(InputReader* reader) :
930 mReader(reader) {
931}
932
933void InputReader::ContextImpl::updateGlobalMetaState() {
934 // lock is already held by the input loop
935 mReader->updateGlobalMetaStateLocked();
936}
937
938int32_t InputReader::ContextImpl::getGlobalMetaState() {
939 // lock is already held by the input loop
940 return mReader->getGlobalMetaStateLocked();
941}
942
943void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
944 // lock is already held by the input loop
945 mReader->disableVirtualKeysUntilLocked(time);
946}
947
948bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
949 InputDevice* device, int32_t keyCode, int32_t scanCode) {
950 // lock is already held by the input loop
951 return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
952}
953
954void InputReader::ContextImpl::fadePointer() {
955 // lock is already held by the input loop
956 mReader->fadePointerLocked();
957}
958
959void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
960 // lock is already held by the input loop
961 mReader->requestTimeoutAtTimeLocked(when);
962}
963
964int32_t InputReader::ContextImpl::bumpGeneration() {
965 // lock is already held by the input loop
966 return mReader->bumpGenerationLocked();
967}
968
Michael Wright842500e2015-03-13 17:32:02 -0700969void InputReader::ContextImpl::getExternalStylusDevices(Vector<InputDeviceInfo>& outDevices) {
970 // lock is already held by whatever called refreshConfigurationLocked
971 mReader->getExternalStylusDevicesLocked(outDevices);
972}
973
974void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
975 mReader->dispatchExternalStylusState(state);
976}
977
Michael Wrightd02c5b62014-02-10 15:10:22 -0800978InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
979 return mReader->mPolicy.get();
980}
981
982InputListenerInterface* InputReader::ContextImpl::getListener() {
983 return mReader->mQueuedListener.get();
984}
985
986EventHubInterface* InputReader::ContextImpl::getEventHub() {
987 return mReader->mEventHub.get();
988}
989
990
991// --- InputReaderThread ---
992
993InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
994 Thread(/*canCallJava*/ true), mReader(reader) {
995}
996
997InputReaderThread::~InputReaderThread() {
998}
999
1000bool InputReaderThread::threadLoop() {
1001 mReader->loopOnce();
1002 return true;
1003}
1004
1005
1006// --- InputDevice ---
1007
1008InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
1009 int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
1010 mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
1011 mIdentifier(identifier), mClasses(classes),
Tim Kilbourn063ff532015-04-08 10:26:18 -07001012 mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001013}
1014
1015InputDevice::~InputDevice() {
1016 size_t numMappers = mMappers.size();
1017 for (size_t i = 0; i < numMappers; i++) {
1018 delete mMappers[i];
1019 }
1020 mMappers.clear();
1021}
1022
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001023bool InputDevice::isEnabled() {
1024 return getEventHub()->isDeviceEnabled(mId);
1025}
1026
1027void InputDevice::setEnabled(bool enabled, nsecs_t when) {
1028 if (isEnabled() == enabled) {
1029 return;
1030 }
1031
1032 if (enabled) {
1033 getEventHub()->enableDevice(mId);
1034 reset(when);
1035 } else {
1036 reset(when);
1037 getEventHub()->disableDevice(mId);
1038 }
1039 // Must change generation to flag this device as changed
1040 bumpGeneration();
1041}
1042
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001043void InputDevice::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001044 InputDeviceInfo deviceInfo;
1045 getDeviceInfo(& deviceInfo);
1046
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001047 dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001048 deviceInfo.getDisplayName().c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001049 dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
1050 dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
1051 dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
1052 dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
1053 dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001054
1055 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
1056 if (!ranges.isEmpty()) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001057 dump += INDENT2 "Motion Ranges:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08001058 for (size_t i = 0; i < ranges.size(); i++) {
1059 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
1060 const char* label = getAxisLabel(range.axis);
1061 char name[32];
1062 if (label) {
1063 strncpy(name, label, sizeof(name));
1064 name[sizeof(name) - 1] = '\0';
1065 } else {
1066 snprintf(name, sizeof(name), "%d", range.axis);
1067 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001068 dump += StringPrintf(INDENT3 "%s: source=0x%08x, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08001069 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
1070 name, range.source, range.min, range.max, range.flat, range.fuzz,
1071 range.resolution);
1072 }
1073 }
1074
1075 size_t numMappers = mMappers.size();
1076 for (size_t i = 0; i < numMappers; i++) {
1077 InputMapper* mapper = mMappers[i];
1078 mapper->dump(dump);
1079 }
1080}
1081
1082void InputDevice::addMapper(InputMapper* mapper) {
1083 mMappers.add(mapper);
1084}
1085
1086void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
1087 mSources = 0;
1088
1089 if (!isIgnored()) {
1090 if (!changes) { // first time only
1091 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
1092 }
1093
1094 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
1095 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
1096 sp<KeyCharacterMap> keyboardLayout =
1097 mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
1098 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
1099 bumpGeneration();
1100 }
1101 }
1102 }
1103
1104 if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
1105 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001106 std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001107 if (mAlias != alias) {
1108 mAlias = alias;
1109 bumpGeneration();
1110 }
1111 }
1112 }
1113
Siarhei Vishniakoue54cb852017-03-21 17:48:16 -07001114 if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
1115 ssize_t index = config->disabledDevices.indexOf(mId);
1116 bool enabled = index < 0;
1117 setEnabled(enabled, when);
1118 }
1119
Michael Wrightd02c5b62014-02-10 15:10:22 -08001120 size_t numMappers = mMappers.size();
1121 for (size_t i = 0; i < numMappers; i++) {
1122 InputMapper* mapper = mMappers[i];
1123 mapper->configure(when, config, changes);
1124 mSources |= mapper->getSources();
1125 }
1126 }
1127}
1128
1129void InputDevice::reset(nsecs_t when) {
1130 size_t numMappers = mMappers.size();
1131 for (size_t i = 0; i < numMappers; i++) {
1132 InputMapper* mapper = mMappers[i];
1133 mapper->reset(when);
1134 }
1135
1136 mContext->updateGlobalMetaState();
1137
1138 notifyReset(when);
1139}
1140
1141void InputDevice::process(const RawEvent* rawEvents, size_t count) {
1142 // Process all of the events in order for each mapper.
1143 // We cannot simply ask each mapper to process them in bulk because mappers may
1144 // have side-effects that must be interleaved. For example, joystick movement events and
1145 // gamepad button presses are handled by different mappers but they should be dispatched
1146 // in the order received.
1147 size_t numMappers = mMappers.size();
Ivan Lozano96f12992017-11-09 14:45:38 -08001148 for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001149#if DEBUG_RAW_EVENTS
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07001150 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08001151 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
1152 rawEvent->when);
1153#endif
1154
1155 if (mDropUntilNextSync) {
1156 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1157 mDropUntilNextSync = false;
1158#if DEBUG_RAW_EVENTS
1159 ALOGD("Recovered from input event buffer overrun.");
1160#endif
1161 } else {
1162#if DEBUG_RAW_EVENTS
1163 ALOGD("Dropped input event while waiting for next input sync.");
1164#endif
1165 }
1166 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001167 ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08001168 mDropUntilNextSync = true;
1169 reset(rawEvent->when);
1170 } else {
1171 for (size_t i = 0; i < numMappers; i++) {
1172 InputMapper* mapper = mMappers[i];
1173 mapper->process(rawEvent);
1174 }
1175 }
Ivan Lozano96f12992017-11-09 14:45:38 -08001176 --count;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001177 }
1178}
1179
1180void InputDevice::timeoutExpired(nsecs_t when) {
1181 size_t numMappers = mMappers.size();
1182 for (size_t i = 0; i < numMappers; i++) {
1183 InputMapper* mapper = mMappers[i];
1184 mapper->timeoutExpired(when);
1185 }
1186}
1187
Michael Wright842500e2015-03-13 17:32:02 -07001188void InputDevice::updateExternalStylusState(const StylusState& state) {
1189 size_t numMappers = mMappers.size();
1190 for (size_t i = 0; i < numMappers; i++) {
1191 InputMapper* mapper = mMappers[i];
1192 mapper->updateExternalStylusState(state);
1193 }
1194}
1195
Michael Wrightd02c5b62014-02-10 15:10:22 -08001196void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
1197 outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
Tim Kilbourn063ff532015-04-08 10:26:18 -07001198 mIsExternal, mHasMic);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001199 size_t numMappers = mMappers.size();
1200 for (size_t i = 0; i < numMappers; i++) {
1201 InputMapper* mapper = mMappers[i];
1202 mapper->populateDeviceInfo(outDeviceInfo);
1203 }
1204}
1205
1206int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1207 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
1208}
1209
1210int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1211 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
1212}
1213
1214int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1215 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
1216}
1217
1218int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
1219 int32_t result = AKEY_STATE_UNKNOWN;
1220 size_t numMappers = mMappers.size();
1221 for (size_t i = 0; i < numMappers; i++) {
1222 InputMapper* mapper = mMappers[i];
1223 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1224 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
1225 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
1226 int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
1227 if (currentResult >= AKEY_STATE_DOWN) {
1228 return currentResult;
1229 } else if (currentResult == AKEY_STATE_UP) {
1230 result = currentResult;
1231 }
1232 }
1233 }
1234 return result;
1235}
1236
1237bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1238 const int32_t* keyCodes, uint8_t* outFlags) {
1239 bool result = false;
1240 size_t numMappers = mMappers.size();
1241 for (size_t i = 0; i < numMappers; i++) {
1242 InputMapper* mapper = mMappers[i];
1243 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1244 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1245 }
1246 }
1247 return result;
1248}
1249
1250void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1251 int32_t token) {
1252 size_t numMappers = mMappers.size();
1253 for (size_t i = 0; i < numMappers; i++) {
1254 InputMapper* mapper = mMappers[i];
1255 mapper->vibrate(pattern, patternSize, repeat, token);
1256 }
1257}
1258
1259void InputDevice::cancelVibrate(int32_t token) {
1260 size_t numMappers = mMappers.size();
1261 for (size_t i = 0; i < numMappers; i++) {
1262 InputMapper* mapper = mMappers[i];
1263 mapper->cancelVibrate(token);
1264 }
1265}
1266
Jeff Brownc9aa6282015-02-11 19:03:28 -08001267void InputDevice::cancelTouch(nsecs_t when) {
1268 size_t numMappers = mMappers.size();
1269 for (size_t i = 0; i < numMappers; i++) {
1270 InputMapper* mapper = mMappers[i];
1271 mapper->cancelTouch(when);
1272 }
1273}
1274
Michael Wrightd02c5b62014-02-10 15:10:22 -08001275int32_t InputDevice::getMetaState() {
1276 int32_t result = 0;
1277 size_t numMappers = mMappers.size();
1278 for (size_t i = 0; i < numMappers; i++) {
1279 InputMapper* mapper = mMappers[i];
1280 result |= mapper->getMetaState();
1281 }
1282 return result;
1283}
1284
Andrii Kulian763a3a42016-03-08 10:46:16 -08001285void InputDevice::updateMetaState(int32_t keyCode) {
1286 size_t numMappers = mMappers.size();
1287 for (size_t i = 0; i < numMappers; i++) {
1288 mMappers[i]->updateMetaState(keyCode);
1289 }
1290}
1291
Michael Wrightd02c5b62014-02-10 15:10:22 -08001292void InputDevice::fadePointer() {
1293 size_t numMappers = mMappers.size();
1294 for (size_t i = 0; i < numMappers; i++) {
1295 InputMapper* mapper = mMappers[i];
1296 mapper->fadePointer();
1297 }
1298}
1299
1300void InputDevice::bumpGeneration() {
1301 mGeneration = mContext->bumpGeneration();
1302}
1303
1304void InputDevice::notifyReset(nsecs_t when) {
1305 NotifyDeviceResetArgs args(when, mId);
1306 mContext->getListener()->notifyDeviceReset(&args);
1307}
1308
1309
1310// --- CursorButtonAccumulator ---
1311
1312CursorButtonAccumulator::CursorButtonAccumulator() {
1313 clearButtons();
1314}
1315
1316void CursorButtonAccumulator::reset(InputDevice* device) {
1317 mBtnLeft = device->isKeyPressed(BTN_LEFT);
1318 mBtnRight = device->isKeyPressed(BTN_RIGHT);
1319 mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
1320 mBtnBack = device->isKeyPressed(BTN_BACK);
1321 mBtnSide = device->isKeyPressed(BTN_SIDE);
1322 mBtnForward = device->isKeyPressed(BTN_FORWARD);
1323 mBtnExtra = device->isKeyPressed(BTN_EXTRA);
1324 mBtnTask = device->isKeyPressed(BTN_TASK);
1325}
1326
1327void CursorButtonAccumulator::clearButtons() {
1328 mBtnLeft = 0;
1329 mBtnRight = 0;
1330 mBtnMiddle = 0;
1331 mBtnBack = 0;
1332 mBtnSide = 0;
1333 mBtnForward = 0;
1334 mBtnExtra = 0;
1335 mBtnTask = 0;
1336}
1337
1338void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1339 if (rawEvent->type == EV_KEY) {
1340 switch (rawEvent->code) {
1341 case BTN_LEFT:
1342 mBtnLeft = rawEvent->value;
1343 break;
1344 case BTN_RIGHT:
1345 mBtnRight = rawEvent->value;
1346 break;
1347 case BTN_MIDDLE:
1348 mBtnMiddle = rawEvent->value;
1349 break;
1350 case BTN_BACK:
1351 mBtnBack = rawEvent->value;
1352 break;
1353 case BTN_SIDE:
1354 mBtnSide = rawEvent->value;
1355 break;
1356 case BTN_FORWARD:
1357 mBtnForward = rawEvent->value;
1358 break;
1359 case BTN_EXTRA:
1360 mBtnExtra = rawEvent->value;
1361 break;
1362 case BTN_TASK:
1363 mBtnTask = rawEvent->value;
1364 break;
1365 }
1366 }
1367}
1368
1369uint32_t CursorButtonAccumulator::getButtonState() const {
1370 uint32_t result = 0;
1371 if (mBtnLeft) {
1372 result |= AMOTION_EVENT_BUTTON_PRIMARY;
1373 }
1374 if (mBtnRight) {
1375 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1376 }
1377 if (mBtnMiddle) {
1378 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1379 }
1380 if (mBtnBack || mBtnSide) {
1381 result |= AMOTION_EVENT_BUTTON_BACK;
1382 }
1383 if (mBtnForward || mBtnExtra) {
1384 result |= AMOTION_EVENT_BUTTON_FORWARD;
1385 }
1386 return result;
1387}
1388
1389
1390// --- CursorMotionAccumulator ---
1391
1392CursorMotionAccumulator::CursorMotionAccumulator() {
1393 clearRelativeAxes();
1394}
1395
1396void CursorMotionAccumulator::reset(InputDevice* device) {
1397 clearRelativeAxes();
1398}
1399
1400void CursorMotionAccumulator::clearRelativeAxes() {
1401 mRelX = 0;
1402 mRelY = 0;
1403}
1404
1405void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1406 if (rawEvent->type == EV_REL) {
1407 switch (rawEvent->code) {
1408 case REL_X:
1409 mRelX = rawEvent->value;
1410 break;
1411 case REL_Y:
1412 mRelY = rawEvent->value;
1413 break;
1414 }
1415 }
1416}
1417
1418void CursorMotionAccumulator::finishSync() {
1419 clearRelativeAxes();
1420}
1421
1422
1423// --- CursorScrollAccumulator ---
1424
1425CursorScrollAccumulator::CursorScrollAccumulator() :
1426 mHaveRelWheel(false), mHaveRelHWheel(false) {
1427 clearRelativeAxes();
1428}
1429
1430void CursorScrollAccumulator::configure(InputDevice* device) {
1431 mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1432 mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1433}
1434
1435void CursorScrollAccumulator::reset(InputDevice* device) {
1436 clearRelativeAxes();
1437}
1438
1439void CursorScrollAccumulator::clearRelativeAxes() {
1440 mRelWheel = 0;
1441 mRelHWheel = 0;
1442}
1443
1444void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
1445 if (rawEvent->type == EV_REL) {
1446 switch (rawEvent->code) {
1447 case REL_WHEEL:
1448 mRelWheel = rawEvent->value;
1449 break;
1450 case REL_HWHEEL:
1451 mRelHWheel = rawEvent->value;
1452 break;
1453 }
1454 }
1455}
1456
1457void CursorScrollAccumulator::finishSync() {
1458 clearRelativeAxes();
1459}
1460
1461
1462// --- TouchButtonAccumulator ---
1463
1464TouchButtonAccumulator::TouchButtonAccumulator() :
1465 mHaveBtnTouch(false), mHaveStylus(false) {
1466 clearButtons();
1467}
1468
1469void TouchButtonAccumulator::configure(InputDevice* device) {
1470 mHaveBtnTouch = device->hasKey(BTN_TOUCH);
1471 mHaveStylus = device->hasKey(BTN_TOOL_PEN)
1472 || device->hasKey(BTN_TOOL_RUBBER)
1473 || device->hasKey(BTN_TOOL_BRUSH)
1474 || device->hasKey(BTN_TOOL_PENCIL)
1475 || device->hasKey(BTN_TOOL_AIRBRUSH);
1476}
1477
1478void TouchButtonAccumulator::reset(InputDevice* device) {
1479 mBtnTouch = device->isKeyPressed(BTN_TOUCH);
1480 mBtnStylus = device->isKeyPressed(BTN_STYLUS);
Michael Wright842500e2015-03-13 17:32:02 -07001481 // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
1482 mBtnStylus2 =
1483 device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001484 mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
1485 mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
1486 mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
1487 mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
1488 mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
1489 mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
1490 mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
1491 mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
1492 mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
1493 mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
1494 mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
1495}
1496
1497void TouchButtonAccumulator::clearButtons() {
1498 mBtnTouch = 0;
1499 mBtnStylus = 0;
1500 mBtnStylus2 = 0;
1501 mBtnToolFinger = 0;
1502 mBtnToolPen = 0;
1503 mBtnToolRubber = 0;
1504 mBtnToolBrush = 0;
1505 mBtnToolPencil = 0;
1506 mBtnToolAirbrush = 0;
1507 mBtnToolMouse = 0;
1508 mBtnToolLens = 0;
1509 mBtnToolDoubleTap = 0;
1510 mBtnToolTripleTap = 0;
1511 mBtnToolQuadTap = 0;
1512}
1513
1514void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1515 if (rawEvent->type == EV_KEY) {
1516 switch (rawEvent->code) {
1517 case BTN_TOUCH:
1518 mBtnTouch = rawEvent->value;
1519 break;
1520 case BTN_STYLUS:
1521 mBtnStylus = rawEvent->value;
1522 break;
1523 case BTN_STYLUS2:
Michael Wright842500e2015-03-13 17:32:02 -07001524 case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
Michael Wrightd02c5b62014-02-10 15:10:22 -08001525 mBtnStylus2 = rawEvent->value;
1526 break;
1527 case BTN_TOOL_FINGER:
1528 mBtnToolFinger = rawEvent->value;
1529 break;
1530 case BTN_TOOL_PEN:
1531 mBtnToolPen = rawEvent->value;
1532 break;
1533 case BTN_TOOL_RUBBER:
1534 mBtnToolRubber = rawEvent->value;
1535 break;
1536 case BTN_TOOL_BRUSH:
1537 mBtnToolBrush = rawEvent->value;
1538 break;
1539 case BTN_TOOL_PENCIL:
1540 mBtnToolPencil = rawEvent->value;
1541 break;
1542 case BTN_TOOL_AIRBRUSH:
1543 mBtnToolAirbrush = rawEvent->value;
1544 break;
1545 case BTN_TOOL_MOUSE:
1546 mBtnToolMouse = rawEvent->value;
1547 break;
1548 case BTN_TOOL_LENS:
1549 mBtnToolLens = rawEvent->value;
1550 break;
1551 case BTN_TOOL_DOUBLETAP:
1552 mBtnToolDoubleTap = rawEvent->value;
1553 break;
1554 case BTN_TOOL_TRIPLETAP:
1555 mBtnToolTripleTap = rawEvent->value;
1556 break;
1557 case BTN_TOOL_QUADTAP:
1558 mBtnToolQuadTap = rawEvent->value;
1559 break;
1560 }
1561 }
1562}
1563
1564uint32_t TouchButtonAccumulator::getButtonState() const {
1565 uint32_t result = 0;
1566 if (mBtnStylus) {
Michael Wright7b159c92015-05-14 14:48:03 +01001567 result |= AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001568 }
1569 if (mBtnStylus2) {
Michael Wright7b159c92015-05-14 14:48:03 +01001570 result |= AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001571 }
1572 return result;
1573}
1574
1575int32_t TouchButtonAccumulator::getToolType() const {
1576 if (mBtnToolMouse || mBtnToolLens) {
1577 return AMOTION_EVENT_TOOL_TYPE_MOUSE;
1578 }
1579 if (mBtnToolRubber) {
1580 return AMOTION_EVENT_TOOL_TYPE_ERASER;
1581 }
1582 if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
1583 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1584 }
1585 if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
1586 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1587 }
1588 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1589}
1590
1591bool TouchButtonAccumulator::isToolActive() const {
1592 return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
1593 || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
1594 || mBtnToolMouse || mBtnToolLens
1595 || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
1596}
1597
1598bool TouchButtonAccumulator::isHovering() const {
1599 return mHaveBtnTouch && !mBtnTouch;
1600}
1601
1602bool TouchButtonAccumulator::hasStylus() const {
1603 return mHaveStylus;
1604}
1605
1606
1607// --- RawPointerAxes ---
1608
1609RawPointerAxes::RawPointerAxes() {
1610 clear();
1611}
1612
1613void RawPointerAxes::clear() {
1614 x.clear();
1615 y.clear();
1616 pressure.clear();
1617 touchMajor.clear();
1618 touchMinor.clear();
1619 toolMajor.clear();
1620 toolMinor.clear();
1621 orientation.clear();
1622 distance.clear();
1623 tiltX.clear();
1624 tiltY.clear();
1625 trackingId.clear();
1626 slot.clear();
1627}
1628
1629
1630// --- RawPointerData ---
1631
1632RawPointerData::RawPointerData() {
1633 clear();
1634}
1635
1636void RawPointerData::clear() {
1637 pointerCount = 0;
1638 clearIdBits();
1639}
1640
1641void RawPointerData::copyFrom(const RawPointerData& other) {
1642 pointerCount = other.pointerCount;
1643 hoveringIdBits = other.hoveringIdBits;
1644 touchingIdBits = other.touchingIdBits;
1645
1646 for (uint32_t i = 0; i < pointerCount; i++) {
1647 pointers[i] = other.pointers[i];
1648
1649 int id = pointers[i].id;
1650 idToIndex[id] = other.idToIndex[id];
1651 }
1652}
1653
1654void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
1655 float x = 0, y = 0;
1656 uint32_t count = touchingIdBits.count();
1657 if (count) {
1658 for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
1659 uint32_t id = idBits.clearFirstMarkedBit();
1660 const Pointer& pointer = pointerForId(id);
1661 x += pointer.x;
1662 y += pointer.y;
1663 }
1664 x /= count;
1665 y /= count;
1666 }
1667 *outX = x;
1668 *outY = y;
1669}
1670
1671
1672// --- CookedPointerData ---
1673
1674CookedPointerData::CookedPointerData() {
1675 clear();
1676}
1677
1678void CookedPointerData::clear() {
1679 pointerCount = 0;
1680 hoveringIdBits.clear();
1681 touchingIdBits.clear();
1682}
1683
1684void CookedPointerData::copyFrom(const CookedPointerData& other) {
1685 pointerCount = other.pointerCount;
1686 hoveringIdBits = other.hoveringIdBits;
1687 touchingIdBits = other.touchingIdBits;
1688
1689 for (uint32_t i = 0; i < pointerCount; i++) {
1690 pointerProperties[i].copyFrom(other.pointerProperties[i]);
1691 pointerCoords[i].copyFrom(other.pointerCoords[i]);
1692
1693 int id = pointerProperties[i].id;
1694 idToIndex[id] = other.idToIndex[id];
1695 }
1696}
1697
1698
1699// --- SingleTouchMotionAccumulator ---
1700
1701SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1702 clearAbsoluteAxes();
1703}
1704
1705void SingleTouchMotionAccumulator::reset(InputDevice* device) {
1706 mAbsX = device->getAbsoluteAxisValue(ABS_X);
1707 mAbsY = device->getAbsoluteAxisValue(ABS_Y);
1708 mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
1709 mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
1710 mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
1711 mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
1712 mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
1713}
1714
1715void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1716 mAbsX = 0;
1717 mAbsY = 0;
1718 mAbsPressure = 0;
1719 mAbsToolWidth = 0;
1720 mAbsDistance = 0;
1721 mAbsTiltX = 0;
1722 mAbsTiltY = 0;
1723}
1724
1725void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1726 if (rawEvent->type == EV_ABS) {
1727 switch (rawEvent->code) {
1728 case ABS_X:
1729 mAbsX = rawEvent->value;
1730 break;
1731 case ABS_Y:
1732 mAbsY = rawEvent->value;
1733 break;
1734 case ABS_PRESSURE:
1735 mAbsPressure = rawEvent->value;
1736 break;
1737 case ABS_TOOL_WIDTH:
1738 mAbsToolWidth = rawEvent->value;
1739 break;
1740 case ABS_DISTANCE:
1741 mAbsDistance = rawEvent->value;
1742 break;
1743 case ABS_TILT_X:
1744 mAbsTiltX = rawEvent->value;
1745 break;
1746 case ABS_TILT_Y:
1747 mAbsTiltY = rawEvent->value;
1748 break;
1749 }
1750 }
1751}
1752
1753
1754// --- MultiTouchMotionAccumulator ---
1755
1756MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
Yi Kong9b14ac62018-07-17 13:48:38 -07001757 mCurrentSlot(-1), mSlots(nullptr), mSlotCount(0), mUsingSlotsProtocol(false),
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08001758 mHaveStylus(false), mDeviceTimestamp(0) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001759}
1760
1761MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1762 delete[] mSlots;
1763}
1764
1765void MultiTouchMotionAccumulator::configure(InputDevice* device,
1766 size_t slotCount, bool usingSlotsProtocol) {
1767 mSlotCount = slotCount;
1768 mUsingSlotsProtocol = usingSlotsProtocol;
1769 mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
1770
1771 delete[] mSlots;
1772 mSlots = new Slot[slotCount];
1773}
1774
1775void MultiTouchMotionAccumulator::reset(InputDevice* device) {
1776 // Unfortunately there is no way to read the initial contents of the slots.
1777 // So when we reset the accumulator, we must assume they are all zeroes.
1778 if (mUsingSlotsProtocol) {
1779 // Query the driver for the current slot index and use it as the initial slot
1780 // before we start reading events from the device. It is possible that the
1781 // current slot index will not be the same as it was when the first event was
1782 // written into the evdev buffer, which means the input mapper could start
1783 // out of sync with the initial state of the events in the evdev buffer.
1784 // In the extremely unlikely case that this happens, the data from
1785 // two slots will be confused until the next ABS_MT_SLOT event is received.
1786 // This can cause the touch point to "jump", but at least there will be
1787 // no stuck touches.
1788 int32_t initialSlot;
1789 status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
1790 ABS_MT_SLOT, &initialSlot);
1791 if (status) {
1792 ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
1793 initialSlot = -1;
1794 }
1795 clearSlots(initialSlot);
1796 } else {
1797 clearSlots(-1);
1798 }
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08001799 mDeviceTimestamp = 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001800}
1801
1802void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
1803 if (mSlots) {
1804 for (size_t i = 0; i < mSlotCount; i++) {
1805 mSlots[i].clear();
1806 }
1807 }
1808 mCurrentSlot = initialSlot;
1809}
1810
1811void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1812 if (rawEvent->type == EV_ABS) {
1813 bool newSlot = false;
1814 if (mUsingSlotsProtocol) {
1815 if (rawEvent->code == ABS_MT_SLOT) {
1816 mCurrentSlot = rawEvent->value;
1817 newSlot = true;
1818 }
1819 } else if (mCurrentSlot < 0) {
1820 mCurrentSlot = 0;
1821 }
1822
1823 if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1824#if DEBUG_POINTERS
1825 if (newSlot) {
1826 ALOGW("MultiTouch device emitted invalid slot index %d but it "
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07001827 "should be between 0 and %zd; ignoring this slot.",
Michael Wrightd02c5b62014-02-10 15:10:22 -08001828 mCurrentSlot, mSlotCount - 1);
1829 }
1830#endif
1831 } else {
1832 Slot* slot = &mSlots[mCurrentSlot];
1833
1834 switch (rawEvent->code) {
1835 case ABS_MT_POSITION_X:
1836 slot->mInUse = true;
1837 slot->mAbsMTPositionX = rawEvent->value;
1838 break;
1839 case ABS_MT_POSITION_Y:
1840 slot->mInUse = true;
1841 slot->mAbsMTPositionY = rawEvent->value;
1842 break;
1843 case ABS_MT_TOUCH_MAJOR:
1844 slot->mInUse = true;
1845 slot->mAbsMTTouchMajor = rawEvent->value;
1846 break;
1847 case ABS_MT_TOUCH_MINOR:
1848 slot->mInUse = true;
1849 slot->mAbsMTTouchMinor = rawEvent->value;
1850 slot->mHaveAbsMTTouchMinor = true;
1851 break;
1852 case ABS_MT_WIDTH_MAJOR:
1853 slot->mInUse = true;
1854 slot->mAbsMTWidthMajor = rawEvent->value;
1855 break;
1856 case ABS_MT_WIDTH_MINOR:
1857 slot->mInUse = true;
1858 slot->mAbsMTWidthMinor = rawEvent->value;
1859 slot->mHaveAbsMTWidthMinor = true;
1860 break;
1861 case ABS_MT_ORIENTATION:
1862 slot->mInUse = true;
1863 slot->mAbsMTOrientation = rawEvent->value;
1864 break;
1865 case ABS_MT_TRACKING_ID:
1866 if (mUsingSlotsProtocol && rawEvent->value < 0) {
1867 // The slot is no longer in use but it retains its previous contents,
1868 // which may be reused for subsequent touches.
1869 slot->mInUse = false;
1870 } else {
1871 slot->mInUse = true;
1872 slot->mAbsMTTrackingId = rawEvent->value;
1873 }
1874 break;
1875 case ABS_MT_PRESSURE:
1876 slot->mInUse = true;
1877 slot->mAbsMTPressure = rawEvent->value;
1878 break;
1879 case ABS_MT_DISTANCE:
1880 slot->mInUse = true;
1881 slot->mAbsMTDistance = rawEvent->value;
1882 break;
1883 case ABS_MT_TOOL_TYPE:
1884 slot->mInUse = true;
1885 slot->mAbsMTToolType = rawEvent->value;
1886 slot->mHaveAbsMTToolType = true;
1887 break;
1888 }
1889 }
1890 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
1891 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1892 mCurrentSlot += 1;
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08001893 } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
1894 mDeviceTimestamp = rawEvent->value;
Michael Wrightd02c5b62014-02-10 15:10:22 -08001895 }
1896}
1897
1898void MultiTouchMotionAccumulator::finishSync() {
1899 if (!mUsingSlotsProtocol) {
1900 clearSlots(-1);
1901 }
1902}
1903
1904bool MultiTouchMotionAccumulator::hasStylus() const {
1905 return mHaveStylus;
1906}
1907
1908
1909// --- MultiTouchMotionAccumulator::Slot ---
1910
1911MultiTouchMotionAccumulator::Slot::Slot() {
1912 clear();
1913}
1914
1915void MultiTouchMotionAccumulator::Slot::clear() {
1916 mInUse = false;
1917 mHaveAbsMTTouchMinor = false;
1918 mHaveAbsMTWidthMinor = false;
1919 mHaveAbsMTToolType = false;
1920 mAbsMTPositionX = 0;
1921 mAbsMTPositionY = 0;
1922 mAbsMTTouchMajor = 0;
1923 mAbsMTTouchMinor = 0;
1924 mAbsMTWidthMajor = 0;
1925 mAbsMTWidthMinor = 0;
1926 mAbsMTOrientation = 0;
1927 mAbsMTTrackingId = -1;
1928 mAbsMTPressure = 0;
1929 mAbsMTDistance = 0;
1930 mAbsMTToolType = 0;
1931}
1932
1933int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1934 if (mHaveAbsMTToolType) {
1935 switch (mAbsMTToolType) {
1936 case MT_TOOL_FINGER:
1937 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1938 case MT_TOOL_PEN:
1939 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1940 }
1941 }
1942 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1943}
1944
1945
1946// --- InputMapper ---
1947
1948InputMapper::InputMapper(InputDevice* device) :
1949 mDevice(device), mContext(device->getContext()) {
1950}
1951
1952InputMapper::~InputMapper() {
1953}
1954
1955void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1956 info->addSource(getSources());
1957}
1958
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08001959void InputMapper::dump(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001960}
1961
1962void InputMapper::configure(nsecs_t when,
1963 const InputReaderConfiguration* config, uint32_t changes) {
1964}
1965
1966void InputMapper::reset(nsecs_t when) {
1967}
1968
1969void InputMapper::timeoutExpired(nsecs_t when) {
1970}
1971
1972int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1973 return AKEY_STATE_UNKNOWN;
1974}
1975
1976int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1977 return AKEY_STATE_UNKNOWN;
1978}
1979
1980int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1981 return AKEY_STATE_UNKNOWN;
1982}
1983
1984bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1985 const int32_t* keyCodes, uint8_t* outFlags) {
1986 return false;
1987}
1988
1989void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1990 int32_t token) {
1991}
1992
1993void InputMapper::cancelVibrate(int32_t token) {
1994}
1995
Jeff Brownc9aa6282015-02-11 19:03:28 -08001996void InputMapper::cancelTouch(nsecs_t when) {
1997}
1998
Michael Wrightd02c5b62014-02-10 15:10:22 -08001999int32_t InputMapper::getMetaState() {
2000 return 0;
2001}
2002
Andrii Kulian763a3a42016-03-08 10:46:16 -08002003void InputMapper::updateMetaState(int32_t keyCode) {
2004}
2005
Michael Wright842500e2015-03-13 17:32:02 -07002006void InputMapper::updateExternalStylusState(const StylusState& state) {
2007
2008}
2009
Michael Wrightd02c5b62014-02-10 15:10:22 -08002010void InputMapper::fadePointer() {
2011}
2012
2013status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
2014 return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
2015}
2016
2017void InputMapper::bumpGeneration() {
2018 mDevice->bumpGeneration();
2019}
2020
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002021void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002022 const RawAbsoluteAxisInfo& axis, const char* name) {
2023 if (axis.valid) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002024 dump += StringPrintf(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002025 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
2026 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002027 dump += StringPrintf(INDENT4 "%s: unknown range\n", name);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002028 }
2029}
2030
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002031void InputMapper::dumpStylusState(std::string& dump, const StylusState& state) {
2032 dump += StringPrintf(INDENT4 "When: %" PRId64 "\n", state.when);
2033 dump += StringPrintf(INDENT4 "Pressure: %f\n", state.pressure);
2034 dump += StringPrintf(INDENT4 "Button State: 0x%08x\n", state.buttons);
2035 dump += StringPrintf(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
Michael Wright842500e2015-03-13 17:32:02 -07002036}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002037
2038// --- SwitchInputMapper ---
2039
2040SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002041 InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002042}
2043
2044SwitchInputMapper::~SwitchInputMapper() {
2045}
2046
2047uint32_t SwitchInputMapper::getSources() {
2048 return AINPUT_SOURCE_SWITCH;
2049}
2050
2051void SwitchInputMapper::process(const RawEvent* rawEvent) {
2052 switch (rawEvent->type) {
2053 case EV_SW:
2054 processSwitch(rawEvent->code, rawEvent->value);
2055 break;
2056
2057 case EV_SYN:
2058 if (rawEvent->code == SYN_REPORT) {
2059 sync(rawEvent->when);
2060 }
2061 }
2062}
2063
2064void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
2065 if (switchCode >= 0 && switchCode < 32) {
2066 if (switchValue) {
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002067 mSwitchValues |= 1 << switchCode;
2068 } else {
2069 mSwitchValues &= ~(1 << switchCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002070 }
2071 mUpdatedSwitchMask |= 1 << switchCode;
2072 }
2073}
2074
2075void SwitchInputMapper::sync(nsecs_t when) {
2076 if (mUpdatedSwitchMask) {
Michael Wright3da3b842014-08-29 16:16:26 -07002077 uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002078 NotifySwitchArgs args(when, 0, updatedSwitchValues, mUpdatedSwitchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002079 getListener()->notifySwitch(&args);
2080
Michael Wrightd02c5b62014-02-10 15:10:22 -08002081 mUpdatedSwitchMask = 0;
2082 }
2083}
2084
2085int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
2086 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
2087}
2088
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002089void SwitchInputMapper::dump(std::string& dump) {
2090 dump += INDENT2 "Switch Input Mapper:\n";
2091 dump += StringPrintf(INDENT3 "SwitchValues: %x\n", mSwitchValues);
Michael Wrightbcbf97e2014-08-29 14:31:32 -07002092}
Michael Wrightd02c5b62014-02-10 15:10:22 -08002093
2094// --- VibratorInputMapper ---
2095
2096VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
2097 InputMapper(device), mVibrating(false) {
2098}
2099
2100VibratorInputMapper::~VibratorInputMapper() {
2101}
2102
2103uint32_t VibratorInputMapper::getSources() {
2104 return 0;
2105}
2106
2107void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2108 InputMapper::populateDeviceInfo(info);
2109
2110 info->setVibrator(true);
2111}
2112
2113void VibratorInputMapper::process(const RawEvent* rawEvent) {
2114 // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
2115}
2116
2117void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
2118 int32_t token) {
2119#if DEBUG_VIBRATOR
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002120 std::string patternStr;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002121 for (size_t i = 0; i < patternSize; i++) {
2122 if (i != 0) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002123 patternStr += ", ";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002124 }
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002125 patternStr += StringPrintf("%" PRId64, pattern[i]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002126 }
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07002127 ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002128 getDeviceId(), patternStr.c_str(), repeat, token);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002129#endif
2130
2131 mVibrating = true;
2132 memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
2133 mPatternSize = patternSize;
2134 mRepeat = repeat;
2135 mToken = token;
2136 mIndex = -1;
2137
2138 nextStep();
2139}
2140
2141void VibratorInputMapper::cancelVibrate(int32_t token) {
2142#if DEBUG_VIBRATOR
2143 ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
2144#endif
2145
2146 if (mVibrating && mToken == token) {
2147 stopVibrating();
2148 }
2149}
2150
2151void VibratorInputMapper::timeoutExpired(nsecs_t when) {
2152 if (mVibrating) {
2153 if (when >= mNextStepTime) {
2154 nextStep();
2155 } else {
2156 getContext()->requestTimeoutAtTime(mNextStepTime);
2157 }
2158 }
2159}
2160
2161void VibratorInputMapper::nextStep() {
2162 mIndex += 1;
2163 if (size_t(mIndex) >= mPatternSize) {
2164 if (mRepeat < 0) {
2165 // We are done.
2166 stopVibrating();
2167 return;
2168 }
2169 mIndex = mRepeat;
2170 }
2171
2172 bool vibratorOn = mIndex & 1;
2173 nsecs_t duration = mPattern[mIndex];
2174 if (vibratorOn) {
2175#if DEBUG_VIBRATOR
Siarhei Vishniakou5d83f602017-09-12 12:40:29 -07002176 ALOGD("nextStep: sending vibrate deviceId=%d, duration=%" PRId64, getDeviceId(), duration);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002177#endif
2178 getEventHub()->vibrate(getDeviceId(), duration);
2179 } else {
2180#if DEBUG_VIBRATOR
2181 ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
2182#endif
2183 getEventHub()->cancelVibrate(getDeviceId());
2184 }
2185 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
2186 mNextStepTime = now + duration;
2187 getContext()->requestTimeoutAtTime(mNextStepTime);
2188#if DEBUG_VIBRATOR
2189 ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
2190#endif
2191}
2192
2193void VibratorInputMapper::stopVibrating() {
2194 mVibrating = false;
2195#if DEBUG_VIBRATOR
2196 ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
2197#endif
2198 getEventHub()->cancelVibrate(getDeviceId());
2199}
2200
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002201void VibratorInputMapper::dump(std::string& dump) {
2202 dump += INDENT2 "Vibrator Input Mapper:\n";
2203 dump += StringPrintf(INDENT3 "Vibrating: %s\n", toString(mVibrating));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002204}
2205
2206
2207// --- KeyboardInputMapper ---
2208
2209KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
2210 uint32_t source, int32_t keyboardType) :
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002211 InputMapper(device), mSource(source), mKeyboardType(keyboardType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002212}
2213
2214KeyboardInputMapper::~KeyboardInputMapper() {
2215}
2216
2217uint32_t KeyboardInputMapper::getSources() {
2218 return mSource;
2219}
2220
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002221int32_t KeyboardInputMapper::getOrientation() {
2222 if (mViewport) {
2223 return mViewport->orientation;
2224 }
2225 return DISPLAY_ORIENTATION_0;
2226}
2227
2228int32_t KeyboardInputMapper::getDisplayId() {
2229 if (mViewport) {
2230 return mViewport->displayId;
2231 }
2232 return ADISPLAY_ID_NONE;
2233}
2234
Michael Wrightd02c5b62014-02-10 15:10:22 -08002235void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2236 InputMapper::populateDeviceInfo(info);
2237
2238 info->setKeyboardType(mKeyboardType);
2239 info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
2240}
2241
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002242void KeyboardInputMapper::dump(std::string& dump) {
2243 dump += INDENT2 "Keyboard Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002244 dumpParameters(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002245 dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002246 dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002247 dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
2248 dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
2249 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002250}
2251
2252
2253void KeyboardInputMapper::configure(nsecs_t when,
2254 const InputReaderConfiguration* config, uint32_t changes) {
2255 InputMapper::configure(when, config, changes);
2256
2257 if (!changes) { // first time only
2258 // Configure basic parameters.
2259 configureParameters();
2260 }
2261
2262 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002263 if (mParameters.orientationAware) {
2264 DisplayViewport dvp;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002265 config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &dvp);
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002266 mViewport = dvp;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002267 }
2268 }
2269}
2270
Ivan Podogovb9afef32017-02-13 15:34:32 +00002271static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
2272 int32_t mapped = 0;
2273 if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
2274 for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
2275 if (stemKeyRotationMap[i][0] == keyCode) {
2276 stemKeyRotationMap[i][1] = mapped;
2277 return;
2278 }
2279 }
2280 }
2281}
2282
Michael Wrightd02c5b62014-02-10 15:10:22 -08002283void KeyboardInputMapper::configureParameters() {
2284 mParameters.orientationAware = false;
Ivan Podogovb9afef32017-02-13 15:34:32 +00002285 const PropertyMap& config = getDevice()->getConfiguration();
2286 config.tryGetProperty(String8("keyboard.orientationAware"),
Michael Wrightd02c5b62014-02-10 15:10:22 -08002287 mParameters.orientationAware);
2288
Michael Wrightd02c5b62014-02-10 15:10:22 -08002289 if (mParameters.orientationAware) {
Ivan Podogovb9afef32017-02-13 15:34:32 +00002290 mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
2291 mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
2292 mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
2293 mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
Michael Wrightd02c5b62014-02-10 15:10:22 -08002294 }
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002295
2296 mParameters.handlesKeyRepeat = false;
Ivan Podogovb9afef32017-02-13 15:34:32 +00002297 config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002298 mParameters.handlesKeyRepeat);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002299}
2300
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002301void KeyboardInputMapper::dumpParameters(std::string& dump) {
2302 dump += INDENT3 "Parameters:\n";
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002303 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002304 toString(mParameters.orientationAware));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002305 dump += StringPrintf(INDENT4 "HandlesKeyRepeat: %s\n",
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002306 toString(mParameters.handlesKeyRepeat));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002307}
2308
2309void KeyboardInputMapper::reset(nsecs_t when) {
2310 mMetaState = AMETA_NONE;
2311 mDownTime = 0;
2312 mKeyDowns.clear();
2313 mCurrentHidUsage = 0;
2314
2315 resetLedState();
2316
2317 InputMapper::reset(when);
2318}
2319
2320void KeyboardInputMapper::process(const RawEvent* rawEvent) {
2321 switch (rawEvent->type) {
2322 case EV_KEY: {
2323 int32_t scanCode = rawEvent->code;
2324 int32_t usageCode = mCurrentHidUsage;
2325 mCurrentHidUsage = 0;
2326
2327 if (isKeyboardOrGamepadKey(scanCode)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002328 processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002329 }
2330 break;
2331 }
2332 case EV_MSC: {
2333 if (rawEvent->code == MSC_SCAN) {
2334 mCurrentHidUsage = rawEvent->value;
2335 }
2336 break;
2337 }
2338 case EV_SYN: {
2339 if (rawEvent->code == SYN_REPORT) {
2340 mCurrentHidUsage = 0;
2341 }
2342 }
2343 }
2344}
2345
2346bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
2347 return scanCode < BTN_MOUSE
2348 || scanCode >= KEY_OK
2349 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
2350 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
2351}
2352
Michael Wright58ba9882017-07-26 16:19:11 +01002353bool KeyboardInputMapper::isMediaKey(int32_t keyCode) {
2354 switch (keyCode) {
2355 case AKEYCODE_MEDIA_PLAY:
2356 case AKEYCODE_MEDIA_PAUSE:
2357 case AKEYCODE_MEDIA_PLAY_PAUSE:
2358 case AKEYCODE_MUTE:
2359 case AKEYCODE_HEADSETHOOK:
2360 case AKEYCODE_MEDIA_STOP:
2361 case AKEYCODE_MEDIA_NEXT:
2362 case AKEYCODE_MEDIA_PREVIOUS:
2363 case AKEYCODE_MEDIA_REWIND:
2364 case AKEYCODE_MEDIA_RECORD:
2365 case AKEYCODE_MEDIA_FAST_FORWARD:
2366 case AKEYCODE_MEDIA_SKIP_FORWARD:
2367 case AKEYCODE_MEDIA_SKIP_BACKWARD:
2368 case AKEYCODE_MEDIA_STEP_FORWARD:
2369 case AKEYCODE_MEDIA_STEP_BACKWARD:
2370 case AKEYCODE_MEDIA_AUDIO_TRACK:
2371 case AKEYCODE_VOLUME_UP:
2372 case AKEYCODE_VOLUME_DOWN:
2373 case AKEYCODE_VOLUME_MUTE:
2374 case AKEYCODE_TV_AUDIO_DESCRIPTION:
2375 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP:
2376 case AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN:
2377 return true;
2378 }
2379 return false;
2380}
2381
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002382void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
2383 int32_t usageCode) {
2384 int32_t keyCode;
2385 int32_t keyMetaState;
2386 uint32_t policyFlags;
2387
2388 if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
2389 &keyCode, &keyMetaState, &policyFlags)) {
2390 keyCode = AKEYCODE_UNKNOWN;
2391 keyMetaState = mMetaState;
2392 policyFlags = 0;
2393 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002394
2395 if (down) {
2396 // Rotate key codes according to orientation if needed.
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002397 if (mParameters.orientationAware) {
2398 keyCode = rotateKeyCode(keyCode, getOrientation());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002399 }
2400
2401 // Add key down.
2402 ssize_t keyDownIndex = findKeyDown(scanCode);
2403 if (keyDownIndex >= 0) {
2404 // key repeat, be sure to use same keycode as before in case of rotation
2405 keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
2406 } else {
2407 // key down
2408 if ((policyFlags & POLICY_FLAG_VIRTUAL)
2409 && mContext->shouldDropVirtualKey(when,
2410 getDevice(), keyCode, scanCode)) {
2411 return;
2412 }
Jeff Brownc9aa6282015-02-11 19:03:28 -08002413 if (policyFlags & POLICY_FLAG_GESTURE) {
2414 mDevice->cancelTouch(when);
2415 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002416
2417 mKeyDowns.push();
2418 KeyDown& keyDown = mKeyDowns.editTop();
2419 keyDown.keyCode = keyCode;
2420 keyDown.scanCode = scanCode;
2421 }
2422
2423 mDownTime = when;
2424 } else {
2425 // Remove key down.
2426 ssize_t keyDownIndex = findKeyDown(scanCode);
2427 if (keyDownIndex >= 0) {
2428 // key up, be sure to use same keycode as before in case of rotation
2429 keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
2430 mKeyDowns.removeAt(size_t(keyDownIndex));
2431 } else {
2432 // key was not actually down
2433 ALOGI("Dropping key up from device %s because the key was not down. "
2434 "keyCode=%d, scanCode=%d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002435 getDeviceName().c_str(), keyCode, scanCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002436 return;
2437 }
2438 }
2439
Andrii Kulian763a3a42016-03-08 10:46:16 -08002440 if (updateMetaStateIfNeeded(keyCode, down)) {
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002441 // If global meta state changed send it along with the key.
2442 // If it has not changed then we'll use what keymap gave us,
2443 // since key replacement logic might temporarily reset a few
2444 // meta bits for given key.
Andrii Kulian763a3a42016-03-08 10:46:16 -08002445 keyMetaState = mMetaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002446 }
2447
2448 nsecs_t downTime = mDownTime;
2449
2450 // Key down on external an keyboard should wake the device.
2451 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
2452 // For internal keyboards, the key layout file should specify the policy flags for
2453 // each wake key individually.
2454 // TODO: Use the input device configuration to control this behavior more finely.
Michael Wright58ba9882017-07-26 16:19:11 +01002455 if (down && getDevice()->isExternal() && !isMediaKey(keyCode)) {
Michael Wright872db4f2014-04-22 15:03:51 -07002456 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002457 }
2458
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002459 if (mParameters.handlesKeyRepeat) {
2460 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
2461 }
2462
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002463 NotifyKeyArgs args(when, getDeviceId(), mSource, getDisplayId(), policyFlags,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002464 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07002465 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002466 getListener()->notifyKey(&args);
2467}
2468
2469ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
2470 size_t n = mKeyDowns.size();
2471 for (size_t i = 0; i < n; i++) {
2472 if (mKeyDowns[i].scanCode == scanCode) {
2473 return i;
2474 }
2475 }
2476 return -1;
2477}
2478
2479int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
2480 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
2481}
2482
2483int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2484 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2485}
2486
2487bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2488 const int32_t* keyCodes, uint8_t* outFlags) {
2489 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
2490}
2491
2492int32_t KeyboardInputMapper::getMetaState() {
2493 return mMetaState;
2494}
2495
Andrii Kulian763a3a42016-03-08 10:46:16 -08002496void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
2497 updateMetaStateIfNeeded(keyCode, false);
2498}
2499
2500bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
2501 int32_t oldMetaState = mMetaState;
2502 int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
2503 bool metaStateChanged = oldMetaState != newMetaState;
2504 if (metaStateChanged) {
2505 mMetaState = newMetaState;
2506 updateLedState(false);
2507
2508 getContext()->updateGlobalMetaState();
2509 }
2510
2511 return metaStateChanged;
2512}
2513
Michael Wrightd02c5b62014-02-10 15:10:22 -08002514void KeyboardInputMapper::resetLedState() {
2515 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
2516 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
2517 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
2518
2519 updateLedState(true);
2520}
2521
2522void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
2523 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
2524 ledState.on = false;
2525}
2526
2527void KeyboardInputMapper::updateLedState(bool reset) {
2528 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
2529 AMETA_CAPS_LOCK_ON, reset);
2530 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
2531 AMETA_NUM_LOCK_ON, reset);
2532 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
2533 AMETA_SCROLL_LOCK_ON, reset);
2534}
2535
2536void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
2537 int32_t led, int32_t modifier, bool reset) {
2538 if (ledState.avail) {
2539 bool desiredState = (mMetaState & modifier) != 0;
2540 if (reset || ledState.on != desiredState) {
2541 getEventHub()->setLedState(getDeviceId(), led, desiredState);
2542 ledState.on = desiredState;
2543 }
2544 }
2545}
2546
2547
2548// --- CursorInputMapper ---
2549
2550CursorInputMapper::CursorInputMapper(InputDevice* device) :
2551 InputMapper(device) {
2552}
2553
2554CursorInputMapper::~CursorInputMapper() {
2555}
2556
2557uint32_t CursorInputMapper::getSources() {
2558 return mSource;
2559}
2560
2561void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2562 InputMapper::populateDeviceInfo(info);
2563
2564 if (mParameters.mode == Parameters::MODE_POINTER) {
2565 float minX, minY, maxX, maxY;
2566 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
2567 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
2568 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
2569 }
2570 } else {
2571 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
2572 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
2573 }
2574 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2575
2576 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2577 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2578 }
2579 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2580 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2581 }
2582}
2583
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002584void CursorInputMapper::dump(std::string& dump) {
2585 dump += INDENT2 "Cursor Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002586 dumpParameters(dump);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002587 dump += StringPrintf(INDENT3 "XScale: %0.3f\n", mXScale);
2588 dump += StringPrintf(INDENT3 "YScale: %0.3f\n", mYScale);
2589 dump += StringPrintf(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
2590 dump += StringPrintf(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
2591 dump += StringPrintf(INDENT3 "HaveVWheel: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002592 toString(mCursorScrollAccumulator.haveRelativeVWheel()));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002593 dump += StringPrintf(INDENT3 "HaveHWheel: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002594 toString(mCursorScrollAccumulator.haveRelativeHWheel()));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002595 dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
2596 dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
2597 dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
2598 dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
2599 dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
2600 dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002601}
2602
2603void CursorInputMapper::configure(nsecs_t when,
2604 const InputReaderConfiguration* config, uint32_t changes) {
2605 InputMapper::configure(when, config, changes);
2606
2607 if (!changes) { // first time only
2608 mCursorScrollAccumulator.configure(getDevice());
2609
2610 // Configure basic parameters.
2611 configureParameters();
2612
2613 // Configure device mode.
2614 switch (mParameters.mode) {
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002615 case Parameters::MODE_POINTER_RELATIVE:
2616 // Should not happen during first time configuration.
2617 ALOGE("Cannot start a device in MODE_POINTER_RELATIVE, starting in MODE_POINTER");
2618 mParameters.mode = Parameters::MODE_POINTER;
2619 // fall through.
Michael Wrightd02c5b62014-02-10 15:10:22 -08002620 case Parameters::MODE_POINTER:
2621 mSource = AINPUT_SOURCE_MOUSE;
2622 mXPrecision = 1.0f;
2623 mYPrecision = 1.0f;
2624 mXScale = 1.0f;
2625 mYScale = 1.0f;
2626 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2627 break;
2628 case Parameters::MODE_NAVIGATION:
2629 mSource = AINPUT_SOURCE_TRACKBALL;
2630 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2631 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2632 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2633 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2634 break;
2635 }
2636
2637 mVWheelScale = 1.0f;
2638 mHWheelScale = 1.0f;
2639 }
2640
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002641 if ((!changes && config->pointerCapture)
2642 || (changes & InputReaderConfiguration::CHANGE_POINTER_CAPTURE)) {
2643 if (config->pointerCapture) {
2644 if (mParameters.mode == Parameters::MODE_POINTER) {
2645 mParameters.mode = Parameters::MODE_POINTER_RELATIVE;
2646 mSource = AINPUT_SOURCE_MOUSE_RELATIVE;
2647 // Keep PointerController around in order to preserve the pointer position.
2648 mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2649 } else {
2650 ALOGE("Cannot request pointer capture, device is not in MODE_POINTER");
2651 }
2652 } else {
2653 if (mParameters.mode == Parameters::MODE_POINTER_RELATIVE) {
2654 mParameters.mode = Parameters::MODE_POINTER;
2655 mSource = AINPUT_SOURCE_MOUSE;
2656 } else {
2657 ALOGE("Cannot release pointer capture, device is not in MODE_POINTER_RELATIVE");
2658 }
2659 }
2660 bumpGeneration();
2661 if (changes) {
2662 getDevice()->notifyReset(when);
2663 }
2664 }
2665
Michael Wrightd02c5b62014-02-10 15:10:22 -08002666 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2667 mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
2668 mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
2669 mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
2670 }
2671
2672 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002673 mOrientation = DISPLAY_ORIENTATION_0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002674 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
2675 DisplayViewport v;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002676 if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &v)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002677 mOrientation = v.orientation;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002678 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002679 }
2680 bumpGeneration();
2681 }
2682}
2683
2684void CursorInputMapper::configureParameters() {
2685 mParameters.mode = Parameters::MODE_POINTER;
2686 String8 cursorModeString;
2687 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
2688 if (cursorModeString == "navigation") {
2689 mParameters.mode = Parameters::MODE_NAVIGATION;
2690 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
2691 ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
2692 }
2693 }
2694
2695 mParameters.orientationAware = false;
2696 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
2697 mParameters.orientationAware);
2698
2699 mParameters.hasAssociatedDisplay = false;
2700 if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
2701 mParameters.hasAssociatedDisplay = true;
2702 }
2703}
2704
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002705void CursorInputMapper::dumpParameters(std::string& dump) {
2706 dump += INDENT3 "Parameters:\n";
2707 dump += StringPrintf(INDENT4 "HasAssociatedDisplay: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002708 toString(mParameters.hasAssociatedDisplay));
2709
2710 switch (mParameters.mode) {
2711 case Parameters::MODE_POINTER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002712 dump += INDENT4 "Mode: pointer\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002713 break;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002714 case Parameters::MODE_POINTER_RELATIVE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002715 dump += INDENT4 "Mode: relative pointer\n";
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002716 break;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002717 case Parameters::MODE_NAVIGATION:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002718 dump += INDENT4 "Mode: navigation\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08002719 break;
2720 default:
2721 ALOG_ASSERT(false);
2722 }
2723
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002724 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08002725 toString(mParameters.orientationAware));
2726}
2727
2728void CursorInputMapper::reset(nsecs_t when) {
2729 mButtonState = 0;
2730 mDownTime = 0;
2731
2732 mPointerVelocityControl.reset();
2733 mWheelXVelocityControl.reset();
2734 mWheelYVelocityControl.reset();
2735
2736 mCursorButtonAccumulator.reset(getDevice());
2737 mCursorMotionAccumulator.reset(getDevice());
2738 mCursorScrollAccumulator.reset(getDevice());
2739
2740 InputMapper::reset(when);
2741}
2742
2743void CursorInputMapper::process(const RawEvent* rawEvent) {
2744 mCursorButtonAccumulator.process(rawEvent);
2745 mCursorMotionAccumulator.process(rawEvent);
2746 mCursorScrollAccumulator.process(rawEvent);
2747
2748 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
2749 sync(rawEvent->when);
2750 }
2751}
2752
2753void CursorInputMapper::sync(nsecs_t when) {
2754 int32_t lastButtonState = mButtonState;
2755 int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
2756 mButtonState = currentButtonState;
2757
2758 bool wasDown = isPointerDown(lastButtonState);
2759 bool down = isPointerDown(currentButtonState);
2760 bool downChanged;
2761 if (!wasDown && down) {
2762 mDownTime = when;
2763 downChanged = true;
2764 } else if (wasDown && !down) {
2765 downChanged = true;
2766 } else {
2767 downChanged = false;
2768 }
2769 nsecs_t downTime = mDownTime;
2770 bool buttonsChanged = currentButtonState != lastButtonState;
Michael Wright7b159c92015-05-14 14:48:03 +01002771 int32_t buttonsPressed = currentButtonState & ~lastButtonState;
2772 int32_t buttonsReleased = lastButtonState & ~currentButtonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002773
2774 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
2775 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
2776 bool moved = deltaX != 0 || deltaY != 0;
2777
2778 // Rotate delta according to orientation if needed.
2779 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
2780 && (deltaX != 0.0f || deltaY != 0.0f)) {
2781 rotateDelta(mOrientation, &deltaX, &deltaY);
2782 }
2783
2784 // Move the pointer.
2785 PointerProperties pointerProperties;
2786 pointerProperties.clear();
2787 pointerProperties.id = 0;
2788 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
2789
2790 PointerCoords pointerCoords;
2791 pointerCoords.clear();
2792
2793 float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
2794 float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
2795 bool scrolled = vscroll != 0 || hscroll != 0;
2796
Yi Kong9b14ac62018-07-17 13:48:38 -07002797 mWheelYVelocityControl.move(when, nullptr, &vscroll);
2798 mWheelXVelocityControl.move(when, &hscroll, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002799
2800 mPointerVelocityControl.move(when, &deltaX, &deltaY);
2801
2802 int32_t displayId;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002803 if (mSource == AINPUT_SOURCE_MOUSE) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002804 if (moved || scrolled || buttonsChanged) {
2805 mPointerController->setPresentation(
2806 PointerControllerInterface::PRESENTATION_POINTER);
2807
2808 if (moved) {
2809 mPointerController->move(deltaX, deltaY);
2810 }
2811
2812 if (buttonsChanged) {
2813 mPointerController->setButtonState(currentButtonState);
2814 }
2815
2816 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2817 }
2818
2819 float x, y;
2820 mPointerController->getPosition(&x, &y);
2821 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2822 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jun Mukaifa1706a2015-12-03 01:14:46 -08002823 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
2824 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002825 displayId = ADISPLAY_ID_DEFAULT;
2826 } else {
2827 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
2828 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
2829 displayId = ADISPLAY_ID_NONE;
2830 }
2831
2832 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
2833
2834 // Moving an external trackball or mouse should wake the device.
2835 // We don't do this for internal cursor devices to prevent them from waking up
2836 // the device in your pocket.
2837 // TODO: Use the input device configuration to control this behavior more finely.
2838 uint32_t policyFlags = 0;
2839 if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
Michael Wright872db4f2014-04-22 15:03:51 -07002840 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002841 }
2842
2843 // Synthesize key down from buttons if needed.
2844 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002845 displayId, policyFlags, lastButtonState, currentButtonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002846
2847 // Send motion event.
2848 if (downChanged || moved || scrolled || buttonsChanged) {
2849 int32_t metaState = mContext->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01002850 int32_t buttonState = lastButtonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002851 int32_t motionEventAction;
2852 if (downChanged) {
2853 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002854 } else if (down || (mSource != AINPUT_SOURCE_MOUSE)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002855 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2856 } else {
2857 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
2858 }
2859
Michael Wright7b159c92015-05-14 14:48:03 +01002860 if (buttonsReleased) {
2861 BitSet32 released(buttonsReleased);
2862 while (!released.isEmpty()) {
2863 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
2864 buttonState &= ~actionButton;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002865 NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01002866 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
2867 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002868 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Michael Wright7b159c92015-05-14 14:48:03 +01002869 mXPrecision, mYPrecision, downTime);
2870 getListener()->notifyMotion(&releaseArgs);
2871 }
2872 }
2873
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002874 NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01002875 motionEventAction, 0, 0, metaState, currentButtonState,
2876 AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002877 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002878 mXPrecision, mYPrecision, downTime);
2879 getListener()->notifyMotion(&args);
2880
Michael Wright7b159c92015-05-14 14:48:03 +01002881 if (buttonsPressed) {
2882 BitSet32 pressed(buttonsPressed);
2883 while (!pressed.isEmpty()) {
2884 int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
2885 buttonState |= actionButton;
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002886 NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01002887 AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
2888 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002889 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Michael Wright7b159c92015-05-14 14:48:03 +01002890 mXPrecision, mYPrecision, downTime);
2891 getListener()->notifyMotion(&pressArgs);
2892 }
2893 }
2894
2895 ALOG_ASSERT(buttonState == currentButtonState);
2896
Michael Wrightd02c5b62014-02-10 15:10:22 -08002897 // Send hover move after UP to tell the application that the mouse is hovering now.
2898 if (motionEventAction == AMOTION_EVENT_ACTION_UP
Vladislav Kaznacheev78f97b32016-12-15 18:14:58 -08002899 && (mSource == AINPUT_SOURCE_MOUSE)) {
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002900 NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01002901 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002902 metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002903 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002904 mXPrecision, mYPrecision, downTime);
2905 getListener()->notifyMotion(&hoverArgs);
2906 }
2907
2908 // Send scroll events.
2909 if (scrolled) {
2910 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2911 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2912
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002913 NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01002914 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002915 AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08002916 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Michael Wrightd02c5b62014-02-10 15:10:22 -08002917 mXPrecision, mYPrecision, downTime);
2918 getListener()->notifyMotion(&scrollArgs);
2919 }
2920 }
2921
2922 // Synthesize key up from buttons if needed.
2923 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01002924 displayId, policyFlags, lastButtonState, currentButtonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002925
2926 mCursorMotionAccumulator.finishSync();
2927 mCursorScrollAccumulator.finishSync();
2928}
2929
2930int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2931 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2932 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2933 } else {
2934 return AKEY_STATE_UNKNOWN;
2935 }
2936}
2937
2938void CursorInputMapper::fadePointer() {
Yi Kong9b14ac62018-07-17 13:48:38 -07002939 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002940 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
2941 }
2942}
2943
Prashant Malani1941ff52015-08-11 18:29:28 -07002944// --- RotaryEncoderInputMapper ---
2945
2946RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
Ivan Podogovad437252016-09-29 16:29:55 +01002947 InputMapper(device), mOrientation(DISPLAY_ORIENTATION_0) {
Prashant Malani1941ff52015-08-11 18:29:28 -07002948 mSource = AINPUT_SOURCE_ROTARY_ENCODER;
2949}
2950
2951RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
2952}
2953
2954uint32_t RotaryEncoderInputMapper::getSources() {
2955 return mSource;
2956}
2957
2958void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2959 InputMapper::populateDeviceInfo(info);
2960
2961 if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
Prashant Malanidae627a2016-01-11 17:08:18 -08002962 float res = 0.0f;
2963 if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
2964 ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
2965 }
2966 if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
2967 mScalingFactor)) {
2968 ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
2969 "default to 1.0!\n");
2970 mScalingFactor = 1.0f;
2971 }
2972 info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
2973 res * mScalingFactor);
Prashant Malani1941ff52015-08-11 18:29:28 -07002974 }
2975}
2976
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08002977void RotaryEncoderInputMapper::dump(std::string& dump) {
2978 dump += INDENT2 "Rotary Encoder Input Mapper:\n";
2979 dump += StringPrintf(INDENT3 "HaveWheel: %s\n",
Prashant Malani1941ff52015-08-11 18:29:28 -07002980 toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
2981}
2982
2983void RotaryEncoderInputMapper::configure(nsecs_t when,
2984 const InputReaderConfiguration* config, uint32_t changes) {
2985 InputMapper::configure(when, config, changes);
2986 if (!changes) {
2987 mRotaryEncoderScrollAccumulator.configure(getDevice());
2988 }
Siarhei Vishniakoud00e7872018-08-09 09:22:45 -07002989 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
Ivan Podogovad437252016-09-29 16:29:55 +01002990 DisplayViewport v;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01002991 if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &v)) {
Ivan Podogovad437252016-09-29 16:29:55 +01002992 mOrientation = v.orientation;
2993 } else {
2994 mOrientation = DISPLAY_ORIENTATION_0;
2995 }
2996 }
Prashant Malani1941ff52015-08-11 18:29:28 -07002997}
2998
2999void RotaryEncoderInputMapper::reset(nsecs_t when) {
3000 mRotaryEncoderScrollAccumulator.reset(getDevice());
3001
3002 InputMapper::reset(when);
3003}
3004
3005void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
3006 mRotaryEncoderScrollAccumulator.process(rawEvent);
3007
3008 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
3009 sync(rawEvent->when);
3010 }
3011}
3012
3013void RotaryEncoderInputMapper::sync(nsecs_t when) {
3014 PointerCoords pointerCoords;
3015 pointerCoords.clear();
3016
3017 PointerProperties pointerProperties;
3018 pointerProperties.clear();
3019 pointerProperties.id = 0;
3020 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
3021
3022 float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
3023 bool scrolled = scroll != 0;
3024
3025 // This is not a pointer, so it's not associated with a display.
3026 int32_t displayId = ADISPLAY_ID_NONE;
3027
3028 // Moving the rotary encoder should wake the device (if specified).
3029 uint32_t policyFlags = 0;
3030 if (scrolled && getDevice()->isExternal()) {
3031 policyFlags |= POLICY_FLAG_WAKE;
3032 }
3033
Ivan Podogovad437252016-09-29 16:29:55 +01003034 if (mOrientation == DISPLAY_ORIENTATION_180) {
3035 scroll = -scroll;
3036 }
3037
Prashant Malani1941ff52015-08-11 18:29:28 -07003038 // Send motion event.
3039 if (scrolled) {
3040 int32_t metaState = mContext->getGlobalMetaState();
Prashant Malanidae627a2016-01-11 17:08:18 -08003041 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
Prashant Malani1941ff52015-08-11 18:29:28 -07003042
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08003043 NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags,
Prashant Malani1941ff52015-08-11 18:29:28 -07003044 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
3045 AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08003046 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Prashant Malani1941ff52015-08-11 18:29:28 -07003047 0, 0, 0);
3048 getListener()->notifyMotion(&scrollArgs);
3049 }
3050
3051 mRotaryEncoderScrollAccumulator.finishSync();
3052}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003053
3054// --- TouchInputMapper ---
3055
3056TouchInputMapper::TouchInputMapper(InputDevice* device) :
3057 InputMapper(device),
3058 mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
3059 mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
Michael Wright358bcc72018-08-21 04:01:07 +01003060 mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0),
Michael Wrightd02c5b62014-02-10 15:10:22 -08003061 mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
3062}
3063
3064TouchInputMapper::~TouchInputMapper() {
3065}
3066
3067uint32_t TouchInputMapper::getSources() {
3068 return mSource;
3069}
3070
3071void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3072 InputMapper::populateDeviceInfo(info);
3073
3074 if (mDeviceMode != DEVICE_MODE_DISABLED) {
3075 info->addMotionRange(mOrientedRanges.x);
3076 info->addMotionRange(mOrientedRanges.y);
3077 info->addMotionRange(mOrientedRanges.pressure);
3078
3079 if (mOrientedRanges.haveSize) {
3080 info->addMotionRange(mOrientedRanges.size);
3081 }
3082
3083 if (mOrientedRanges.haveTouchSize) {
3084 info->addMotionRange(mOrientedRanges.touchMajor);
3085 info->addMotionRange(mOrientedRanges.touchMinor);
3086 }
3087
3088 if (mOrientedRanges.haveToolSize) {
3089 info->addMotionRange(mOrientedRanges.toolMajor);
3090 info->addMotionRange(mOrientedRanges.toolMinor);
3091 }
3092
3093 if (mOrientedRanges.haveOrientation) {
3094 info->addMotionRange(mOrientedRanges.orientation);
3095 }
3096
3097 if (mOrientedRanges.haveDistance) {
3098 info->addMotionRange(mOrientedRanges.distance);
3099 }
3100
3101 if (mOrientedRanges.haveTilt) {
3102 info->addMotionRange(mOrientedRanges.tilt);
3103 }
3104
3105 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
3106 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3107 0.0f);
3108 }
3109 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
3110 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
3111 0.0f);
3112 }
3113 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
3114 const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
3115 const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
3116 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
3117 x.fuzz, x.resolution);
3118 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
3119 y.fuzz, y.resolution);
3120 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
3121 x.fuzz, x.resolution);
3122 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
3123 y.fuzz, y.resolution);
3124 }
3125 info->setButtonUnderPad(mParameters.hasButtonUnderPad);
3126 }
3127}
3128
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003129void TouchInputMapper::dump(std::string& dump) {
3130 dump += StringPrintf(INDENT2 "Touch Input Mapper (mode - %s):\n", modeToString(mDeviceMode));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003131 dumpParameters(dump);
3132 dumpVirtualKeys(dump);
3133 dumpRawPointerAxes(dump);
3134 dumpCalibration(dump);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07003135 dumpAffineTransformation(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003136 dumpSurface(dump);
3137
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003138 dump += StringPrintf(INDENT3 "Translation and Scaling Factors:\n");
3139 dump += StringPrintf(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
3140 dump += StringPrintf(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
3141 dump += StringPrintf(INDENT4 "XScale: %0.3f\n", mXScale);
3142 dump += StringPrintf(INDENT4 "YScale: %0.3f\n", mYScale);
3143 dump += StringPrintf(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
3144 dump += StringPrintf(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
3145 dump += StringPrintf(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
3146 dump += StringPrintf(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
3147 dump += StringPrintf(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
3148 dump += StringPrintf(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
3149 dump += StringPrintf(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
3150 dump += StringPrintf(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
3151 dump += StringPrintf(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
3152 dump += StringPrintf(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
3153 dump += StringPrintf(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
3154 dump += StringPrintf(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003155
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003156 dump += StringPrintf(INDENT3 "Last Raw Button State: 0x%08x\n", mLastRawState.buttonState);
3157 dump += StringPrintf(INDENT3 "Last Raw Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07003158 mLastRawState.rawPointerData.pointerCount);
3159 for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
3160 const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003161 dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003162 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
3163 "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
3164 "toolType=%d, isHovering=%s\n", i,
3165 pointer.id, pointer.x, pointer.y, pointer.pressure,
3166 pointer.touchMajor, pointer.touchMinor,
3167 pointer.toolMajor, pointer.toolMinor,
3168 pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
3169 pointer.toolType, toString(pointer.isHovering));
3170 }
3171
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003172 dump += StringPrintf(INDENT3 "Last Cooked Button State: 0x%08x\n", mLastCookedState.buttonState);
3173 dump += StringPrintf(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07003174 mLastCookedState.cookedPointerData.pointerCount);
3175 for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
3176 const PointerProperties& pointerProperties =
3177 mLastCookedState.cookedPointerData.pointerProperties[i];
3178 const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003179 dump += StringPrintf(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003180 "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
3181 "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
3182 "toolType=%d, isHovering=%s\n", i,
3183 pointerProperties.id,
3184 pointerCoords.getX(),
3185 pointerCoords.getY(),
3186 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
3187 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
3188 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
3189 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
3190 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
3191 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
3192 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
3193 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
3194 pointerProperties.toolType,
Michael Wright842500e2015-03-13 17:32:02 -07003195 toString(mLastCookedState.cookedPointerData.isHovering(i)));
Michael Wrightd02c5b62014-02-10 15:10:22 -08003196 }
3197
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003198 dump += INDENT3 "Stylus Fusion:\n";
3199 dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
Michael Wright842500e2015-03-13 17:32:02 -07003200 toString(mExternalStylusConnected));
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003201 dump += StringPrintf(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
3202 dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
Michael Wright43fd19f2015-04-21 19:02:58 +01003203 mExternalStylusFusionTimeout);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003204 dump += INDENT3 "External Stylus State:\n";
Michael Wright842500e2015-03-13 17:32:02 -07003205 dumpStylusState(dump, mExternalStylusState);
3206
Michael Wrightd02c5b62014-02-10 15:10:22 -08003207 if (mDeviceMode == DEVICE_MODE_POINTER) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003208 dump += StringPrintf(INDENT3 "Pointer Gesture Detector:\n");
3209 dump += StringPrintf(INDENT4 "XMovementScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003210 mPointerXMovementScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003211 dump += StringPrintf(INDENT4 "YMovementScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003212 mPointerYMovementScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003213 dump += StringPrintf(INDENT4 "XZoomScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003214 mPointerXZoomScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003215 dump += StringPrintf(INDENT4 "YZoomScale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003216 mPointerYZoomScale);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003217 dump += StringPrintf(INDENT4 "MaxSwipeWidth: %f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003218 mPointerGestureMaxSwipeWidth);
3219 }
3220}
3221
Santos Cordonfa5cf462017-04-05 10:37:00 -07003222const char* TouchInputMapper::modeToString(DeviceMode deviceMode) {
3223 switch (deviceMode) {
3224 case DEVICE_MODE_DISABLED:
3225 return "disabled";
3226 case DEVICE_MODE_DIRECT:
3227 return "direct";
3228 case DEVICE_MODE_UNSCALED:
3229 return "unscaled";
3230 case DEVICE_MODE_NAVIGATION:
3231 return "navigation";
3232 case DEVICE_MODE_POINTER:
3233 return "pointer";
3234 }
3235 return "unknown";
3236}
3237
Michael Wrightd02c5b62014-02-10 15:10:22 -08003238void TouchInputMapper::configure(nsecs_t when,
3239 const InputReaderConfiguration* config, uint32_t changes) {
3240 InputMapper::configure(when, config, changes);
3241
3242 mConfig = *config;
3243
3244 if (!changes) { // first time only
3245 // Configure basic parameters.
3246 configureParameters();
3247
3248 // Configure common accumulators.
3249 mCursorScrollAccumulator.configure(getDevice());
3250 mTouchButtonAccumulator.configure(getDevice());
3251
3252 // Configure absolute axis information.
3253 configureRawPointerAxes();
3254
3255 // Prepare input device calibration.
3256 parseCalibration();
3257 resolveCalibration();
3258 }
3259
Michael Wright842500e2015-03-13 17:32:02 -07003260 if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
Jason Gerecke12d6baa2014-01-27 18:34:20 -08003261 // Update location calibration to reflect current settings
3262 updateAffineTransformation();
3263 }
3264
Michael Wrightd02c5b62014-02-10 15:10:22 -08003265 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
3266 // Update pointer speed.
3267 mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
3268 mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
3269 mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
3270 }
3271
3272 bool resetNeeded = false;
3273 if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
3274 | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
Michael Wright842500e2015-03-13 17:32:02 -07003275 | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
3276 | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003277 // Configure device sources, surface dimensions, orientation and
3278 // scaling factors.
3279 configureSurface(when, &resetNeeded);
3280 }
3281
3282 if (changes && resetNeeded) {
3283 // Send reset, unless this is the first time the device has been configured,
3284 // in which case the reader will call reset itself after all mappers are ready.
3285 getDevice()->notifyReset(when);
3286 }
3287}
3288
Michael Wright842500e2015-03-13 17:32:02 -07003289void TouchInputMapper::resolveExternalStylusPresence() {
3290 Vector<InputDeviceInfo> devices;
3291 mContext->getExternalStylusDevices(devices);
3292 mExternalStylusConnected = !devices.isEmpty();
3293
3294 if (!mExternalStylusConnected) {
3295 resetExternalStylus();
3296 }
3297}
3298
Michael Wrightd02c5b62014-02-10 15:10:22 -08003299void TouchInputMapper::configureParameters() {
3300 // Use the pointer presentation mode for devices that do not support distinct
3301 // multitouch. The spot-based presentation relies on being able to accurately
3302 // locate two or more fingers on the touch pad.
3303 mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003304 ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003305
3306 String8 gestureModeString;
3307 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
3308 gestureModeString)) {
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003309 if (gestureModeString == "single-touch") {
3310 mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
3311 } else if (gestureModeString == "multi-touch") {
3312 mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003313 } else if (gestureModeString != "default") {
3314 ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
3315 }
3316 }
3317
3318 if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
3319 // The device is a touch screen.
3320 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3321 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
3322 // The device is a pointing device like a track pad.
3323 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3324 } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
3325 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
3326 // The device is a cursor device with a touch pad attached.
3327 // By default don't use the touch pad to move the pointer.
3328 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
3329 } else {
3330 // The device is a touch pad of unknown purpose.
3331 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3332 }
3333
3334 mParameters.hasButtonUnderPad=
3335 getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
3336
3337 String8 deviceTypeString;
3338 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
3339 deviceTypeString)) {
3340 if (deviceTypeString == "touchScreen") {
3341 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3342 } else if (deviceTypeString == "touchPad") {
3343 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
3344 } else if (deviceTypeString == "touchNavigation") {
3345 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
3346 } else if (deviceTypeString == "pointer") {
3347 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
3348 } else if (deviceTypeString != "default") {
3349 ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
3350 }
3351 }
3352
3353 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
3354 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
3355 mParameters.orientationAware);
3356
3357 mParameters.hasAssociatedDisplay = false;
3358 mParameters.associatedDisplayIsExternal = false;
3359 if (mParameters.orientationAware
3360 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3361 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
3362 mParameters.hasAssociatedDisplay = true;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003363 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
3364 mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003365 String8 uniqueDisplayId;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003366 getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003367 uniqueDisplayId);
3368 mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
Santos Cordonfa5cf462017-04-05 10:37:00 -07003369 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003370 }
Jeff Brownc5e24422014-02-26 18:48:51 -08003371
3372 // Initial downs on external touch devices should wake the device.
3373 // Normally we don't do this for internal touch screens to prevent them from waking
3374 // up in your pocket but you can enable it using the input device configuration.
3375 mParameters.wake = getDevice()->isExternal();
3376 getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"),
3377 mParameters.wake);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003378}
3379
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003380void TouchInputMapper::dumpParameters(std::string& dump) {
3381 dump += INDENT3 "Parameters:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003382
3383 switch (mParameters.gestureMode) {
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003384 case Parameters::GESTURE_MODE_SINGLE_TOUCH:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003385 dump += INDENT4 "GestureMode: single-touch\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003386 break;
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04003387 case Parameters::GESTURE_MODE_MULTI_TOUCH:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003388 dump += INDENT4 "GestureMode: multi-touch\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003389 break;
3390 default:
3391 assert(false);
3392 }
3393
3394 switch (mParameters.deviceType) {
3395 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003396 dump += INDENT4 "DeviceType: touchScreen\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003397 break;
3398 case Parameters::DEVICE_TYPE_TOUCH_PAD:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003399 dump += INDENT4 "DeviceType: touchPad\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003400 break;
3401 case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003402 dump += INDENT4 "DeviceType: touchNavigation\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003403 break;
3404 case Parameters::DEVICE_TYPE_POINTER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003405 dump += INDENT4 "DeviceType: pointer\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003406 break;
3407 default:
3408 ALOG_ASSERT(false);
3409 }
3410
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003411 dump += StringPrintf(
Santos Cordonfa5cf462017-04-05 10:37:00 -07003412 INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s, displayId='%s'\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003413 toString(mParameters.hasAssociatedDisplay),
Santos Cordonfa5cf462017-04-05 10:37:00 -07003414 toString(mParameters.associatedDisplayIsExternal),
3415 mParameters.uniqueDisplayId.c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003416 dump += StringPrintf(INDENT4 "OrientationAware: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08003417 toString(mParameters.orientationAware));
3418}
3419
3420void TouchInputMapper::configureRawPointerAxes() {
3421 mRawPointerAxes.clear();
3422}
3423
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003424void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
3425 dump += INDENT3 "Raw Touch Axes:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003426 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
3427 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
3428 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
3429 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
3430 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
3431 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
3432 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
3433 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
3434 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
3435 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
3436 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
3437 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
3438 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
3439}
3440
Michael Wright842500e2015-03-13 17:32:02 -07003441bool TouchInputMapper::hasExternalStylus() const {
3442 return mExternalStylusConnected;
3443}
3444
Michael Wrightd02c5b62014-02-10 15:10:22 -08003445void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
3446 int32_t oldDeviceMode = mDeviceMode;
3447
Michael Wright842500e2015-03-13 17:32:02 -07003448 resolveExternalStylusPresence();
3449
Michael Wrightd02c5b62014-02-10 15:10:22 -08003450 // Determine device mode.
3451 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
3452 && mConfig.pointerGesturesEnabled) {
3453 mSource = AINPUT_SOURCE_MOUSE;
3454 mDeviceMode = DEVICE_MODE_POINTER;
3455 if (hasStylus()) {
3456 mSource |= AINPUT_SOURCE_STYLUS;
3457 }
3458 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3459 && mParameters.hasAssociatedDisplay) {
3460 mSource = AINPUT_SOURCE_TOUCHSCREEN;
3461 mDeviceMode = DEVICE_MODE_DIRECT;
Michael Wright2f78b682015-06-12 15:25:08 +01003462 if (hasStylus()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003463 mSource |= AINPUT_SOURCE_STYLUS;
3464 }
Michael Wright2f78b682015-06-12 15:25:08 +01003465 if (hasExternalStylus()) {
3466 mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
3467 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003468 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
3469 mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
3470 mDeviceMode = DEVICE_MODE_NAVIGATION;
3471 } else {
3472 mSource = AINPUT_SOURCE_TOUCHPAD;
3473 mDeviceMode = DEVICE_MODE_UNSCALED;
3474 }
3475
3476 // Ensure we have valid X and Y axes.
3477 if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
3478 ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003479 "The device will be inoperable.", getDeviceName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003480 mDeviceMode = DEVICE_MODE_DISABLED;
3481 return;
3482 }
3483
3484 // Raw width and height in the natural orientation.
3485 int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
3486 int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
3487
3488 // Get associated display dimensions.
3489 DisplayViewport newViewport;
3490 if (mParameters.hasAssociatedDisplay) {
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003491 std::string uniqueDisplayId;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003492 ViewportType viewportTypeToUse;
3493
3494 if (mParameters.associatedDisplayIsExternal) {
3495 viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003496 } else if (!mParameters.uniqueDisplayId.empty()) {
Santos Cordonfa5cf462017-04-05 10:37:00 -07003497 // If the IDC file specified a unique display Id, then it expects to be linked to a
3498 // virtual display with the same unique ID.
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003499 uniqueDisplayId = mParameters.uniqueDisplayId;
Santos Cordonfa5cf462017-04-05 10:37:00 -07003500 viewportTypeToUse = ViewportType::VIEWPORT_VIRTUAL;
3501 } else {
3502 viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
3503 }
3504
3505 if (!mConfig.getDisplayViewport(viewportTypeToUse, uniqueDisplayId, &newViewport)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003506 ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
3507 "display. The device will be inoperable until the display size "
3508 "becomes available.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003509 getDeviceName().c_str());
Michael Wrightd02c5b62014-02-10 15:10:22 -08003510 mDeviceMode = DEVICE_MODE_DISABLED;
3511 return;
3512 }
3513 } else {
3514 newViewport.setNonDisplayViewport(rawWidth, rawHeight);
3515 }
3516 bool viewportChanged = mViewport != newViewport;
3517 if (viewportChanged) {
3518 mViewport = newViewport;
3519
3520 if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
3521 // Convert rotated viewport to natural surface coordinates.
3522 int32_t naturalLogicalWidth, naturalLogicalHeight;
3523 int32_t naturalPhysicalWidth, naturalPhysicalHeight;
3524 int32_t naturalPhysicalLeft, naturalPhysicalTop;
3525 int32_t naturalDeviceWidth, naturalDeviceHeight;
3526 switch (mViewport.orientation) {
3527 case DISPLAY_ORIENTATION_90:
3528 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3529 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3530 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3531 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3532 naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
3533 naturalPhysicalTop = mViewport.physicalLeft;
3534 naturalDeviceWidth = mViewport.deviceHeight;
3535 naturalDeviceHeight = mViewport.deviceWidth;
3536 break;
3537 case DISPLAY_ORIENTATION_180:
3538 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3539 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3540 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3541 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3542 naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
3543 naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
3544 naturalDeviceWidth = mViewport.deviceWidth;
3545 naturalDeviceHeight = mViewport.deviceHeight;
3546 break;
3547 case DISPLAY_ORIENTATION_270:
3548 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3549 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3550 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3551 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3552 naturalPhysicalLeft = mViewport.physicalTop;
3553 naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
3554 naturalDeviceWidth = mViewport.deviceHeight;
3555 naturalDeviceHeight = mViewport.deviceWidth;
3556 break;
3557 case DISPLAY_ORIENTATION_0:
3558 default:
3559 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3560 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3561 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3562 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3563 naturalPhysicalLeft = mViewport.physicalLeft;
3564 naturalPhysicalTop = mViewport.physicalTop;
3565 naturalDeviceWidth = mViewport.deviceWidth;
3566 naturalDeviceHeight = mViewport.deviceHeight;
3567 break;
3568 }
3569
Siarhei Vishniakoud6343922018-07-06 23:33:37 +01003570 if (naturalPhysicalHeight == 0 || naturalPhysicalWidth == 0) {
3571 ALOGE("Viewport is not set properly: %s", mViewport.toString().c_str());
3572 naturalPhysicalHeight = naturalPhysicalHeight == 0 ? 1 : naturalPhysicalHeight;
3573 naturalPhysicalWidth = naturalPhysicalWidth == 0 ? 1 : naturalPhysicalWidth;
3574 }
3575
Michael Wright358bcc72018-08-21 04:01:07 +01003576 mPhysicalWidth = naturalPhysicalWidth;
3577 mPhysicalHeight = naturalPhysicalHeight;
3578 mPhysicalLeft = naturalPhysicalLeft;
3579 mPhysicalTop = naturalPhysicalTop;
3580
Michael Wrightd02c5b62014-02-10 15:10:22 -08003581 mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
3582 mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
3583 mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
3584 mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
3585
3586 mSurfaceOrientation = mParameters.orientationAware ?
3587 mViewport.orientation : DISPLAY_ORIENTATION_0;
3588 } else {
Michael Wright358bcc72018-08-21 04:01:07 +01003589 mPhysicalWidth = rawWidth;
3590 mPhysicalHeight = rawHeight;
3591 mPhysicalLeft = 0;
3592 mPhysicalTop = 0;
3593
Michael Wrightd02c5b62014-02-10 15:10:22 -08003594 mSurfaceWidth = rawWidth;
3595 mSurfaceHeight = rawHeight;
3596 mSurfaceLeft = 0;
3597 mSurfaceTop = 0;
3598 mSurfaceOrientation = DISPLAY_ORIENTATION_0;
3599 }
3600 }
3601
3602 // If moving between pointer modes, need to reset some state.
3603 bool deviceModeChanged = mDeviceMode != oldDeviceMode;
3604 if (deviceModeChanged) {
3605 mOrientedRanges.clear();
3606 }
3607
3608 // Create pointer controller if needed.
3609 if (mDeviceMode == DEVICE_MODE_POINTER ||
3610 (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
Yi Kong9b14ac62018-07-17 13:48:38 -07003611 if (mPointerController == nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003612 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
3613 }
3614 } else {
3615 mPointerController.clear();
3616 }
3617
3618 if (viewportChanged || deviceModeChanged) {
3619 ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
3620 "display id %d",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01003621 getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
Michael Wrightd02c5b62014-02-10 15:10:22 -08003622 mSurfaceOrientation, mDeviceMode, mViewport.displayId);
3623
3624 // Configure X and Y factors.
3625 mXScale = float(mSurfaceWidth) / rawWidth;
3626 mYScale = float(mSurfaceHeight) / rawHeight;
3627 mXTranslate = -mSurfaceLeft;
3628 mYTranslate = -mSurfaceTop;
3629 mXPrecision = 1.0f / mXScale;
3630 mYPrecision = 1.0f / mYScale;
3631
3632 mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
3633 mOrientedRanges.x.source = mSource;
3634 mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
3635 mOrientedRanges.y.source = mSource;
3636
3637 configureVirtualKeys();
3638
3639 // Scale factor for terms that are not oriented in a particular axis.
3640 // If the pixels are square then xScale == yScale otherwise we fake it
3641 // by choosing an average.
3642 mGeometricScale = avg(mXScale, mYScale);
3643
3644 // Size of diagonal axis.
3645 float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
3646
3647 // Size factors.
3648 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
3649 if (mRawPointerAxes.touchMajor.valid
3650 && mRawPointerAxes.touchMajor.maxValue != 0) {
3651 mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
3652 } else if (mRawPointerAxes.toolMajor.valid
3653 && mRawPointerAxes.toolMajor.maxValue != 0) {
3654 mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
3655 } else {
3656 mSizeScale = 0.0f;
3657 }
3658
3659 mOrientedRanges.haveTouchSize = true;
3660 mOrientedRanges.haveToolSize = true;
3661 mOrientedRanges.haveSize = true;
3662
3663 mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
3664 mOrientedRanges.touchMajor.source = mSource;
3665 mOrientedRanges.touchMajor.min = 0;
3666 mOrientedRanges.touchMajor.max = diagonalSize;
3667 mOrientedRanges.touchMajor.flat = 0;
3668 mOrientedRanges.touchMajor.fuzz = 0;
3669 mOrientedRanges.touchMajor.resolution = 0;
3670
3671 mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
3672 mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
3673
3674 mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
3675 mOrientedRanges.toolMajor.source = mSource;
3676 mOrientedRanges.toolMajor.min = 0;
3677 mOrientedRanges.toolMajor.max = diagonalSize;
3678 mOrientedRanges.toolMajor.flat = 0;
3679 mOrientedRanges.toolMajor.fuzz = 0;
3680 mOrientedRanges.toolMajor.resolution = 0;
3681
3682 mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
3683 mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
3684
3685 mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
3686 mOrientedRanges.size.source = mSource;
3687 mOrientedRanges.size.min = 0;
3688 mOrientedRanges.size.max = 1.0;
3689 mOrientedRanges.size.flat = 0;
3690 mOrientedRanges.size.fuzz = 0;
3691 mOrientedRanges.size.resolution = 0;
3692 } else {
3693 mSizeScale = 0.0f;
3694 }
3695
3696 // Pressure factors.
3697 mPressureScale = 0;
Michael Wrightaa449c92017-12-13 21:21:43 +00003698 float pressureMax = 1.0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003699 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
3700 || mCalibration.pressureCalibration
3701 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
3702 if (mCalibration.havePressureScale) {
3703 mPressureScale = mCalibration.pressureScale;
Michael Wrightaa449c92017-12-13 21:21:43 +00003704 pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003705 } else if (mRawPointerAxes.pressure.valid
3706 && mRawPointerAxes.pressure.maxValue != 0) {
3707 mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
3708 }
3709 }
3710
3711 mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
3712 mOrientedRanges.pressure.source = mSource;
3713 mOrientedRanges.pressure.min = 0;
Michael Wrightaa449c92017-12-13 21:21:43 +00003714 mOrientedRanges.pressure.max = pressureMax;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003715 mOrientedRanges.pressure.flat = 0;
3716 mOrientedRanges.pressure.fuzz = 0;
3717 mOrientedRanges.pressure.resolution = 0;
3718
3719 // Tilt
3720 mTiltXCenter = 0;
3721 mTiltXScale = 0;
3722 mTiltYCenter = 0;
3723 mTiltYScale = 0;
3724 mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
3725 if (mHaveTilt) {
3726 mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
3727 mRawPointerAxes.tiltX.maxValue);
3728 mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
3729 mRawPointerAxes.tiltY.maxValue);
3730 mTiltXScale = M_PI / 180;
3731 mTiltYScale = M_PI / 180;
3732
3733 mOrientedRanges.haveTilt = true;
3734
3735 mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
3736 mOrientedRanges.tilt.source = mSource;
3737 mOrientedRanges.tilt.min = 0;
3738 mOrientedRanges.tilt.max = M_PI_2;
3739 mOrientedRanges.tilt.flat = 0;
3740 mOrientedRanges.tilt.fuzz = 0;
3741 mOrientedRanges.tilt.resolution = 0;
3742 }
3743
3744 // Orientation
3745 mOrientationScale = 0;
3746 if (mHaveTilt) {
3747 mOrientedRanges.haveOrientation = true;
3748
3749 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3750 mOrientedRanges.orientation.source = mSource;
3751 mOrientedRanges.orientation.min = -M_PI;
3752 mOrientedRanges.orientation.max = M_PI;
3753 mOrientedRanges.orientation.flat = 0;
3754 mOrientedRanges.orientation.fuzz = 0;
3755 mOrientedRanges.orientation.resolution = 0;
3756 } else if (mCalibration.orientationCalibration !=
3757 Calibration::ORIENTATION_CALIBRATION_NONE) {
3758 if (mCalibration.orientationCalibration
3759 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
3760 if (mRawPointerAxes.orientation.valid) {
3761 if (mRawPointerAxes.orientation.maxValue > 0) {
3762 mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
3763 } else if (mRawPointerAxes.orientation.minValue < 0) {
3764 mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
3765 } else {
3766 mOrientationScale = 0;
3767 }
3768 }
3769 }
3770
3771 mOrientedRanges.haveOrientation = true;
3772
3773 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3774 mOrientedRanges.orientation.source = mSource;
3775 mOrientedRanges.orientation.min = -M_PI_2;
3776 mOrientedRanges.orientation.max = M_PI_2;
3777 mOrientedRanges.orientation.flat = 0;
3778 mOrientedRanges.orientation.fuzz = 0;
3779 mOrientedRanges.orientation.resolution = 0;
3780 }
3781
3782 // Distance
3783 mDistanceScale = 0;
3784 if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
3785 if (mCalibration.distanceCalibration
3786 == Calibration::DISTANCE_CALIBRATION_SCALED) {
3787 if (mCalibration.haveDistanceScale) {
3788 mDistanceScale = mCalibration.distanceScale;
3789 } else {
3790 mDistanceScale = 1.0f;
3791 }
3792 }
3793
3794 mOrientedRanges.haveDistance = true;
3795
3796 mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
3797 mOrientedRanges.distance.source = mSource;
3798 mOrientedRanges.distance.min =
3799 mRawPointerAxes.distance.minValue * mDistanceScale;
3800 mOrientedRanges.distance.max =
3801 mRawPointerAxes.distance.maxValue * mDistanceScale;
3802 mOrientedRanges.distance.flat = 0;
3803 mOrientedRanges.distance.fuzz =
3804 mRawPointerAxes.distance.fuzz * mDistanceScale;
3805 mOrientedRanges.distance.resolution = 0;
3806 }
3807
3808 // Compute oriented precision, scales and ranges.
3809 // Note that the maximum value reported is an inclusive maximum value so it is one
3810 // unit less than the total width or height of surface.
3811 switch (mSurfaceOrientation) {
3812 case DISPLAY_ORIENTATION_90:
3813 case DISPLAY_ORIENTATION_270:
3814 mOrientedXPrecision = mYPrecision;
3815 mOrientedYPrecision = mXPrecision;
3816
3817 mOrientedRanges.x.min = mYTranslate;
3818 mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
3819 mOrientedRanges.x.flat = 0;
3820 mOrientedRanges.x.fuzz = 0;
3821 mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
3822
3823 mOrientedRanges.y.min = mXTranslate;
3824 mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
3825 mOrientedRanges.y.flat = 0;
3826 mOrientedRanges.y.fuzz = 0;
3827 mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
3828 break;
3829
3830 default:
3831 mOrientedXPrecision = mXPrecision;
3832 mOrientedYPrecision = mYPrecision;
3833
3834 mOrientedRanges.x.min = mXTranslate;
3835 mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
3836 mOrientedRanges.x.flat = 0;
3837 mOrientedRanges.x.fuzz = 0;
3838 mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
3839
3840 mOrientedRanges.y.min = mYTranslate;
3841 mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
3842 mOrientedRanges.y.flat = 0;
3843 mOrientedRanges.y.fuzz = 0;
3844 mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
3845 break;
3846 }
3847
Jason Gerecke71b16e82014-03-10 09:47:59 -07003848 // Location
3849 updateAffineTransformation();
3850
Michael Wrightd02c5b62014-02-10 15:10:22 -08003851 if (mDeviceMode == DEVICE_MODE_POINTER) {
3852 // Compute pointer gesture detection parameters.
3853 float rawDiagonal = hypotf(rawWidth, rawHeight);
3854 float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
3855
3856 // Scale movements such that one whole swipe of the touch pad covers a
3857 // given area relative to the diagonal size of the display when no acceleration
3858 // is applied.
3859 // Assume that the touch pad has a square aspect ratio such that movements in
3860 // X and Y of the same number of raw units cover the same physical distance.
3861 mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
3862 * displayDiagonal / rawDiagonal;
3863 mPointerYMovementScale = mPointerXMovementScale;
3864
3865 // Scale zooms to cover a smaller range of the display than movements do.
3866 // This value determines the area around the pointer that is affected by freeform
3867 // pointer gestures.
3868 mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
3869 * displayDiagonal / rawDiagonal;
3870 mPointerYZoomScale = mPointerXZoomScale;
3871
3872 // Max width between pointers to detect a swipe gesture is more than some fraction
3873 // of the diagonal axis of the touch pad. Touches that are wider than this are
3874 // translated into freeform gestures.
3875 mPointerGestureMaxSwipeWidth =
3876 mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
3877
3878 // Abort current pointer usages because the state has changed.
3879 abortPointerUsage(when, 0 /*policyFlags*/);
3880 }
3881
3882 // Inform the dispatcher about the changes.
3883 *outResetNeeded = true;
3884 bumpGeneration();
3885 }
3886}
3887
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003888void TouchInputMapper::dumpSurface(std::string& dump) {
Siarhei Vishniakoud6343922018-07-06 23:33:37 +01003889 dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003890 dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
3891 dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
3892 dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
3893 dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
Michael Wright358bcc72018-08-21 04:01:07 +01003894 dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
3895 dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
3896 dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
3897 dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003898 dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003899}
3900
3901void TouchInputMapper::configureVirtualKeys() {
3902 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
3903 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
3904
3905 mVirtualKeys.clear();
3906
3907 if (virtualKeyDefinitions.size() == 0) {
3908 return;
3909 }
3910
3911 mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
3912
3913 int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
3914 int32_t touchScreenTop = mRawPointerAxes.y.minValue;
3915 int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
3916 int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
3917
3918 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
3919 const VirtualKeyDefinition& virtualKeyDefinition =
3920 virtualKeyDefinitions[i];
3921
3922 mVirtualKeys.add();
3923 VirtualKey& virtualKey = mVirtualKeys.editTop();
3924
3925 virtualKey.scanCode = virtualKeyDefinition.scanCode;
3926 int32_t keyCode;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07003927 int32_t dummyKeyMetaState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003928 uint32_t flags;
Dmitry Torokhov0faaa0b2015-09-24 13:13:55 -07003929 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0,
3930 &keyCode, &dummyKeyMetaState, &flags)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003931 ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
3932 virtualKey.scanCode);
3933 mVirtualKeys.pop(); // drop the key
3934 continue;
3935 }
3936
3937 virtualKey.keyCode = keyCode;
3938 virtualKey.flags = flags;
3939
3940 // convert the key definition's display coordinates into touch coordinates for a hit box
3941 int32_t halfWidth = virtualKeyDefinition.width / 2;
3942 int32_t halfHeight = virtualKeyDefinition.height / 2;
3943
3944 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
3945 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3946 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
3947 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3948 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
3949 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3950 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
3951 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3952 }
3953}
3954
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003955void TouchInputMapper::dumpVirtualKeys(std::string& dump) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003956 if (!mVirtualKeys.isEmpty()) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003957 dump += INDENT3 "Virtual Keys:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08003958
3959 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
3960 const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08003961 dump += StringPrintf(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003962 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
3963 i, virtualKey.scanCode, virtualKey.keyCode,
3964 virtualKey.hitLeft, virtualKey.hitRight,
3965 virtualKey.hitTop, virtualKey.hitBottom);
3966 }
3967 }
3968}
3969
3970void TouchInputMapper::parseCalibration() {
3971 const PropertyMap& in = getDevice()->getConfiguration();
3972 Calibration& out = mCalibration;
3973
3974 // Size
3975 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
3976 String8 sizeCalibrationString;
3977 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
3978 if (sizeCalibrationString == "none") {
3979 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3980 } else if (sizeCalibrationString == "geometric") {
3981 out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3982 } else if (sizeCalibrationString == "diameter") {
3983 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
3984 } else if (sizeCalibrationString == "box") {
3985 out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
3986 } else if (sizeCalibrationString == "area") {
3987 out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
3988 } else if (sizeCalibrationString != "default") {
3989 ALOGW("Invalid value for touch.size.calibration: '%s'",
3990 sizeCalibrationString.string());
3991 }
3992 }
3993
3994 out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
3995 out.sizeScale);
3996 out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
3997 out.sizeBias);
3998 out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
3999 out.sizeIsSummed);
4000
4001 // Pressure
4002 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
4003 String8 pressureCalibrationString;
4004 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
4005 if (pressureCalibrationString == "none") {
4006 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
4007 } else if (pressureCalibrationString == "physical") {
4008 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
4009 } else if (pressureCalibrationString == "amplitude") {
4010 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
4011 } else if (pressureCalibrationString != "default") {
4012 ALOGW("Invalid value for touch.pressure.calibration: '%s'",
4013 pressureCalibrationString.string());
4014 }
4015 }
4016
4017 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
4018 out.pressureScale);
4019
4020 // Orientation
4021 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
4022 String8 orientationCalibrationString;
4023 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
4024 if (orientationCalibrationString == "none") {
4025 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
4026 } else if (orientationCalibrationString == "interpolated") {
4027 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
4028 } else if (orientationCalibrationString == "vector") {
4029 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
4030 } else if (orientationCalibrationString != "default") {
4031 ALOGW("Invalid value for touch.orientation.calibration: '%s'",
4032 orientationCalibrationString.string());
4033 }
4034 }
4035
4036 // Distance
4037 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
4038 String8 distanceCalibrationString;
4039 if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
4040 if (distanceCalibrationString == "none") {
4041 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
4042 } else if (distanceCalibrationString == "scaled") {
4043 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
4044 } else if (distanceCalibrationString != "default") {
4045 ALOGW("Invalid value for touch.distance.calibration: '%s'",
4046 distanceCalibrationString.string());
4047 }
4048 }
4049
4050 out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
4051 out.distanceScale);
4052
4053 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
4054 String8 coverageCalibrationString;
4055 if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
4056 if (coverageCalibrationString == "none") {
4057 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
4058 } else if (coverageCalibrationString == "box") {
4059 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
4060 } else if (coverageCalibrationString != "default") {
4061 ALOGW("Invalid value for touch.coverage.calibration: '%s'",
4062 coverageCalibrationString.string());
4063 }
4064 }
4065}
4066
4067void TouchInputMapper::resolveCalibration() {
4068 // Size
4069 if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
4070 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
4071 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
4072 }
4073 } else {
4074 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
4075 }
4076
4077 // Pressure
4078 if (mRawPointerAxes.pressure.valid) {
4079 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
4080 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
4081 }
4082 } else {
4083 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
4084 }
4085
4086 // Orientation
4087 if (mRawPointerAxes.orientation.valid) {
4088 if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
4089 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
4090 }
4091 } else {
4092 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
4093 }
4094
4095 // Distance
4096 if (mRawPointerAxes.distance.valid) {
4097 if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
4098 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
4099 }
4100 } else {
4101 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
4102 }
4103
4104 // Coverage
4105 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
4106 mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
4107 }
4108}
4109
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004110void TouchInputMapper::dumpCalibration(std::string& dump) {
4111 dump += INDENT3 "Calibration:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004112
4113 // Size
4114 switch (mCalibration.sizeCalibration) {
4115 case Calibration::SIZE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004116 dump += INDENT4 "touch.size.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004117 break;
4118 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004119 dump += INDENT4 "touch.size.calibration: geometric\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004120 break;
4121 case Calibration::SIZE_CALIBRATION_DIAMETER:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004122 dump += INDENT4 "touch.size.calibration: diameter\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004123 break;
4124 case Calibration::SIZE_CALIBRATION_BOX:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004125 dump += INDENT4 "touch.size.calibration: box\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004126 break;
4127 case Calibration::SIZE_CALIBRATION_AREA:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004128 dump += INDENT4 "touch.size.calibration: area\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004129 break;
4130 default:
4131 ALOG_ASSERT(false);
4132 }
4133
4134 if (mCalibration.haveSizeScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004135 dump += StringPrintf(INDENT4 "touch.size.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004136 mCalibration.sizeScale);
4137 }
4138
4139 if (mCalibration.haveSizeBias) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004140 dump += StringPrintf(INDENT4 "touch.size.bias: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004141 mCalibration.sizeBias);
4142 }
4143
4144 if (mCalibration.haveSizeIsSummed) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004145 dump += StringPrintf(INDENT4 "touch.size.isSummed: %s\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004146 toString(mCalibration.sizeIsSummed));
4147 }
4148
4149 // Pressure
4150 switch (mCalibration.pressureCalibration) {
4151 case Calibration::PRESSURE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004152 dump += INDENT4 "touch.pressure.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004153 break;
4154 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004155 dump += INDENT4 "touch.pressure.calibration: physical\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004156 break;
4157 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004158 dump += INDENT4 "touch.pressure.calibration: amplitude\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004159 break;
4160 default:
4161 ALOG_ASSERT(false);
4162 }
4163
4164 if (mCalibration.havePressureScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004165 dump += StringPrintf(INDENT4 "touch.pressure.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004166 mCalibration.pressureScale);
4167 }
4168
4169 // Orientation
4170 switch (mCalibration.orientationCalibration) {
4171 case Calibration::ORIENTATION_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004172 dump += INDENT4 "touch.orientation.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004173 break;
4174 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004175 dump += INDENT4 "touch.orientation.calibration: interpolated\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004176 break;
4177 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004178 dump += INDENT4 "touch.orientation.calibration: vector\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004179 break;
4180 default:
4181 ALOG_ASSERT(false);
4182 }
4183
4184 // Distance
4185 switch (mCalibration.distanceCalibration) {
4186 case Calibration::DISTANCE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004187 dump += INDENT4 "touch.distance.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004188 break;
4189 case Calibration::DISTANCE_CALIBRATION_SCALED:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004190 dump += INDENT4 "touch.distance.calibration: scaled\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004191 break;
4192 default:
4193 ALOG_ASSERT(false);
4194 }
4195
4196 if (mCalibration.haveDistanceScale) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004197 dump += StringPrintf(INDENT4 "touch.distance.scale: %0.3f\n",
Michael Wrightd02c5b62014-02-10 15:10:22 -08004198 mCalibration.distanceScale);
4199 }
4200
4201 switch (mCalibration.coverageCalibration) {
4202 case Calibration::COVERAGE_CALIBRATION_NONE:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004203 dump += INDENT4 "touch.coverage.calibration: none\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004204 break;
4205 case Calibration::COVERAGE_CALIBRATION_BOX:
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004206 dump += INDENT4 "touch.coverage.calibration: box\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08004207 break;
4208 default:
4209 ALOG_ASSERT(false);
4210 }
4211}
4212
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004213void TouchInputMapper::dumpAffineTransformation(std::string& dump) {
4214 dump += INDENT3 "Affine Transformation:\n";
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004215
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08004216 dump += StringPrintf(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
4217 dump += StringPrintf(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
4218 dump += StringPrintf(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
4219 dump += StringPrintf(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
4220 dump += StringPrintf(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
4221 dump += StringPrintf(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004222}
4223
Jason Gerecke12d6baa2014-01-27 18:34:20 -08004224void TouchInputMapper::updateAffineTransformation() {
Jason Gerecke71b16e82014-03-10 09:47:59 -07004225 mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
4226 mSurfaceOrientation);
Jason Gerecke12d6baa2014-01-27 18:34:20 -08004227}
4228
Michael Wrightd02c5b62014-02-10 15:10:22 -08004229void TouchInputMapper::reset(nsecs_t when) {
4230 mCursorButtonAccumulator.reset(getDevice());
4231 mCursorScrollAccumulator.reset(getDevice());
4232 mTouchButtonAccumulator.reset(getDevice());
4233
4234 mPointerVelocityControl.reset();
4235 mWheelXVelocityControl.reset();
4236 mWheelYVelocityControl.reset();
4237
Michael Wright842500e2015-03-13 17:32:02 -07004238 mRawStatesPending.clear();
4239 mCurrentRawState.clear();
4240 mCurrentCookedState.clear();
4241 mLastRawState.clear();
4242 mLastCookedState.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004243 mPointerUsage = POINTER_USAGE_NONE;
4244 mSentHoverEnter = false;
Michael Wright842500e2015-03-13 17:32:02 -07004245 mHavePointerIds = false;
Michael Wright8e812822015-06-22 16:18:21 +01004246 mCurrentMotionAborted = false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004247 mDownTime = 0;
4248
4249 mCurrentVirtualKey.down = false;
4250
4251 mPointerGesture.reset();
4252 mPointerSimple.reset();
Michael Wright842500e2015-03-13 17:32:02 -07004253 resetExternalStylus();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004254
Yi Kong9b14ac62018-07-17 13:48:38 -07004255 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004256 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4257 mPointerController->clearSpots();
4258 }
4259
4260 InputMapper::reset(when);
4261}
4262
Michael Wright842500e2015-03-13 17:32:02 -07004263void TouchInputMapper::resetExternalStylus() {
4264 mExternalStylusState.clear();
4265 mExternalStylusId = -1;
Michael Wright43fd19f2015-04-21 19:02:58 +01004266 mExternalStylusFusionTimeout = LLONG_MAX;
Michael Wright842500e2015-03-13 17:32:02 -07004267 mExternalStylusDataPending = false;
4268}
4269
Michael Wright43fd19f2015-04-21 19:02:58 +01004270void TouchInputMapper::clearStylusDataPendingFlags() {
4271 mExternalStylusDataPending = false;
4272 mExternalStylusFusionTimeout = LLONG_MAX;
4273}
4274
Michael Wrightd02c5b62014-02-10 15:10:22 -08004275void TouchInputMapper::process(const RawEvent* rawEvent) {
4276 mCursorButtonAccumulator.process(rawEvent);
4277 mCursorScrollAccumulator.process(rawEvent);
4278 mTouchButtonAccumulator.process(rawEvent);
4279
4280 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
4281 sync(rawEvent->when);
4282 }
4283}
4284
4285void TouchInputMapper::sync(nsecs_t when) {
Michael Wright842500e2015-03-13 17:32:02 -07004286 const RawState* last = mRawStatesPending.isEmpty() ?
4287 &mCurrentRawState : &mRawStatesPending.top();
4288
4289 // Push a new state.
4290 mRawStatesPending.push();
4291 RawState* next = &mRawStatesPending.editTop();
4292 next->clear();
4293 next->when = when;
4294
Michael Wrightd02c5b62014-02-10 15:10:22 -08004295 // Sync button state.
Michael Wright842500e2015-03-13 17:32:02 -07004296 next->buttonState = mTouchButtonAccumulator.getButtonState()
Michael Wrightd02c5b62014-02-10 15:10:22 -08004297 | mCursorButtonAccumulator.getButtonState();
4298
Michael Wright842500e2015-03-13 17:32:02 -07004299 // Sync scroll
4300 next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
4301 next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004302 mCursorScrollAccumulator.finishSync();
4303
Michael Wright842500e2015-03-13 17:32:02 -07004304 // Sync touch
4305 syncTouch(when, next);
4306
4307 // Assign pointer ids.
4308 if (!mHavePointerIds) {
4309 assignPointerIds(last, next);
4310 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08004311
4312#if DEBUG_RAW_EVENTS
Michael Wright842500e2015-03-13 17:32:02 -07004313 ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
4314 "hovering ids 0x%08x -> 0x%08x",
4315 last->rawPointerData.pointerCount,
4316 next->rawPointerData.pointerCount,
4317 last->rawPointerData.touchingIdBits.value,
4318 next->rawPointerData.touchingIdBits.value,
4319 last->rawPointerData.hoveringIdBits.value,
4320 next->rawPointerData.hoveringIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004321#endif
4322
Michael Wright842500e2015-03-13 17:32:02 -07004323 processRawTouches(false /*timeout*/);
4324}
Michael Wrightd02c5b62014-02-10 15:10:22 -08004325
Michael Wright842500e2015-03-13 17:32:02 -07004326void TouchInputMapper::processRawTouches(bool timeout) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004327 if (mDeviceMode == DEVICE_MODE_DISABLED) {
4328 // Drop all input if the device is disabled.
Michael Wright842500e2015-03-13 17:32:02 -07004329 mCurrentRawState.clear();
4330 mRawStatesPending.clear();
4331 return;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004332 }
4333
Michael Wright842500e2015-03-13 17:32:02 -07004334 // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
4335 // valid and must go through the full cook and dispatch cycle. This ensures that anything
4336 // touching the current state will only observe the events that have been dispatched to the
4337 // rest of the pipeline.
4338 const size_t N = mRawStatesPending.size();
4339 size_t count;
4340 for(count = 0; count < N; count++) {
4341 const RawState& next = mRawStatesPending[count];
4342
4343 // A failure to assign the stylus id means that we're waiting on stylus data
4344 // and so should defer the rest of the pipeline.
4345 if (assignExternalStylusId(next, timeout)) {
4346 break;
4347 }
4348
4349 // All ready to go.
Michael Wright43fd19f2015-04-21 19:02:58 +01004350 clearStylusDataPendingFlags();
Michael Wright842500e2015-03-13 17:32:02 -07004351 mCurrentRawState.copyFrom(next);
Michael Wright43fd19f2015-04-21 19:02:58 +01004352 if (mCurrentRawState.when < mLastRawState.when) {
4353 mCurrentRawState.when = mLastRawState.when;
4354 }
Michael Wright842500e2015-03-13 17:32:02 -07004355 cookAndDispatch(mCurrentRawState.when);
4356 }
4357 if (count != 0) {
4358 mRawStatesPending.removeItemsAt(0, count);
4359 }
4360
Michael Wright842500e2015-03-13 17:32:02 -07004361 if (mExternalStylusDataPending) {
Michael Wright43fd19f2015-04-21 19:02:58 +01004362 if (timeout) {
4363 nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
4364 clearStylusDataPendingFlags();
4365 mCurrentRawState.copyFrom(mLastRawState);
4366#if DEBUG_STYLUS_FUSION
4367 ALOGD("Timeout expired, synthesizing event with new stylus data");
4368#endif
4369 cookAndDispatch(when);
4370 } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
4371 mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
4372 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
4373 }
Michael Wright842500e2015-03-13 17:32:02 -07004374 }
4375}
4376
4377void TouchInputMapper::cookAndDispatch(nsecs_t when) {
4378 // Always start with a clean state.
4379 mCurrentCookedState.clear();
4380
4381 // Apply stylus buttons to current raw state.
4382 applyExternalStylusButtonState(when);
4383
4384 // Handle policy on initial down or hover events.
4385 bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4386 && mCurrentRawState.rawPointerData.pointerCount != 0;
4387
4388 uint32_t policyFlags = 0;
4389 bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
4390 if (initialDown || buttonsPressed) {
4391 // If this is a touch screen, hide the pointer on an initial down.
4392 if (mDeviceMode == DEVICE_MODE_DIRECT) {
4393 getContext()->fadePointer();
4394 }
4395
4396 if (mParameters.wake) {
4397 policyFlags |= POLICY_FLAG_WAKE;
4398 }
4399 }
4400
4401 // Consume raw off-screen touches before cooking pointer data.
4402 // If touches are consumed, subsequent code will not receive any pointer data.
4403 if (consumeRawTouches(when, policyFlags)) {
4404 mCurrentRawState.rawPointerData.clear();
4405 }
4406
4407 // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
4408 // with cooked pointer data that has the same ids and indices as the raw data.
4409 // The following code can use either the raw or cooked data, as needed.
4410 cookPointerData();
4411
4412 // Apply stylus pressure to current cooked state.
4413 applyExternalStylusTouchState(when);
4414
4415 // Synthesize key down from raw buttons if needed.
4416 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004417 mViewport.displayId, policyFlags,
4418 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
Michael Wright842500e2015-03-13 17:32:02 -07004419
4420 // Dispatch the touches either directly or by translation through a pointer on screen.
4421 if (mDeviceMode == DEVICE_MODE_POINTER) {
4422 for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
4423 !idBits.isEmpty(); ) {
4424 uint32_t id = idBits.clearFirstMarkedBit();
4425 const RawPointerData::Pointer& pointer =
4426 mCurrentRawState.rawPointerData.pointerForId(id);
4427 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
4428 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4429 mCurrentCookedState.stylusIdBits.markBit(id);
4430 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
4431 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4432 mCurrentCookedState.fingerIdBits.markBit(id);
4433 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
4434 mCurrentCookedState.mouseIdBits.markBit(id);
4435 }
4436 }
4437 for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
4438 !idBits.isEmpty(); ) {
4439 uint32_t id = idBits.clearFirstMarkedBit();
4440 const RawPointerData::Pointer& pointer =
4441 mCurrentRawState.rawPointerData.pointerForId(id);
4442 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
4443 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4444 mCurrentCookedState.stylusIdBits.markBit(id);
4445 }
4446 }
4447
4448 // Stylus takes precedence over all tools, then mouse, then finger.
4449 PointerUsage pointerUsage = mPointerUsage;
4450 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
4451 mCurrentCookedState.mouseIdBits.clear();
4452 mCurrentCookedState.fingerIdBits.clear();
4453 pointerUsage = POINTER_USAGE_STYLUS;
4454 } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
4455 mCurrentCookedState.fingerIdBits.clear();
4456 pointerUsage = POINTER_USAGE_MOUSE;
4457 } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
4458 isPointerDown(mCurrentRawState.buttonState)) {
4459 pointerUsage = POINTER_USAGE_GESTURES;
4460 }
4461
4462 dispatchPointerUsage(when, policyFlags, pointerUsage);
4463 } else {
4464 if (mDeviceMode == DEVICE_MODE_DIRECT
Yi Kong9b14ac62018-07-17 13:48:38 -07004465 && mConfig.showTouches && mPointerController != nullptr) {
Michael Wright842500e2015-03-13 17:32:02 -07004466 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
4467 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4468
4469 mPointerController->setButtonState(mCurrentRawState.buttonState);
4470 mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
4471 mCurrentCookedState.cookedPointerData.idToIndex,
4472 mCurrentCookedState.cookedPointerData.touchingIdBits);
4473 }
4474
Michael Wright8e812822015-06-22 16:18:21 +01004475 if (!mCurrentMotionAborted) {
4476 dispatchButtonRelease(when, policyFlags);
4477 dispatchHoverExit(when, policyFlags);
4478 dispatchTouches(when, policyFlags);
4479 dispatchHoverEnterAndMove(when, policyFlags);
4480 dispatchButtonPress(when, policyFlags);
4481 }
4482
4483 if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
4484 mCurrentMotionAborted = false;
4485 }
Michael Wright842500e2015-03-13 17:32:02 -07004486 }
4487
4488 // Synthesize key up from raw buttons if needed.
4489 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004490 mViewport.displayId, policyFlags,
4491 mLastCookedState.buttonState, mCurrentCookedState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004492
4493 // Clear some transient state.
Michael Wright842500e2015-03-13 17:32:02 -07004494 mCurrentRawState.rawVScroll = 0;
4495 mCurrentRawState.rawHScroll = 0;
4496
4497 // Copy current touch to last touch in preparation for the next cycle.
4498 mLastRawState.copyFrom(mCurrentRawState);
4499 mLastCookedState.copyFrom(mCurrentCookedState);
4500}
4501
4502void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
Michael Wright7b159c92015-05-14 14:48:03 +01004503 if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus() && mExternalStylusId != -1) {
Michael Wright842500e2015-03-13 17:32:02 -07004504 mCurrentRawState.buttonState |= mExternalStylusState.buttons;
4505 }
4506}
4507
4508void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
Michael Wright53dca3a2015-04-23 17:39:53 +01004509 CookedPointerData& currentPointerData = mCurrentCookedState.cookedPointerData;
4510 const CookedPointerData& lastPointerData = mLastCookedState.cookedPointerData;
Michael Wright842500e2015-03-13 17:32:02 -07004511
Michael Wright53dca3a2015-04-23 17:39:53 +01004512 if (mExternalStylusId != -1 && currentPointerData.isTouching(mExternalStylusId)) {
4513 float pressure = mExternalStylusState.pressure;
4514 if (pressure == 0.0f && lastPointerData.isTouching(mExternalStylusId)) {
4515 const PointerCoords& coords = lastPointerData.pointerCoordsForId(mExternalStylusId);
4516 pressure = coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
4517 }
4518 PointerCoords& coords = currentPointerData.editPointerCoordsWithId(mExternalStylusId);
4519 coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
4520
4521 PointerProperties& properties =
4522 currentPointerData.editPointerPropertiesWithId(mExternalStylusId);
Michael Wright842500e2015-03-13 17:32:02 -07004523 if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4524 properties.toolType = mExternalStylusState.toolType;
4525 }
4526 }
4527}
4528
4529bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
4530 if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
4531 return false;
4532 }
4533
4534 const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4535 && state.rawPointerData.pointerCount != 0;
4536 if (initialDown) {
4537 if (mExternalStylusState.pressure != 0.0f) {
4538#if DEBUG_STYLUS_FUSION
4539 ALOGD("Have both stylus and touch data, beginning fusion");
4540#endif
4541 mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
4542 } else if (timeout) {
4543#if DEBUG_STYLUS_FUSION
4544 ALOGD("Timeout expired, assuming touch is not a stylus.");
4545#endif
4546 resetExternalStylus();
4547 } else {
Michael Wright43fd19f2015-04-21 19:02:58 +01004548 if (mExternalStylusFusionTimeout == LLONG_MAX) {
4549 mExternalStylusFusionTimeout = state.when + EXTERNAL_STYLUS_DATA_TIMEOUT;
Michael Wright842500e2015-03-13 17:32:02 -07004550 }
4551#if DEBUG_STYLUS_FUSION
4552 ALOGD("No stylus data but stylus is connected, requesting timeout "
Michael Wright43fd19f2015-04-21 19:02:58 +01004553 "(%" PRId64 "ms)", mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004554#endif
Michael Wright43fd19f2015-04-21 19:02:58 +01004555 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004556 return true;
4557 }
4558 }
4559
4560 // Check if the stylus pointer has gone up.
4561 if (mExternalStylusId != -1 &&
4562 !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
4563#if DEBUG_STYLUS_FUSION
4564 ALOGD("Stylus pointer is going up");
4565#endif
4566 mExternalStylusId = -1;
4567 }
4568
4569 return false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004570}
4571
4572void TouchInputMapper::timeoutExpired(nsecs_t when) {
4573 if (mDeviceMode == DEVICE_MODE_POINTER) {
4574 if (mPointerUsage == POINTER_USAGE_GESTURES) {
4575 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
4576 }
Michael Wright842500e2015-03-13 17:32:02 -07004577 } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
Michael Wright43fd19f2015-04-21 19:02:58 +01004578 if (mExternalStylusFusionTimeout < when) {
Michael Wright842500e2015-03-13 17:32:02 -07004579 processRawTouches(true /*timeout*/);
Michael Wright43fd19f2015-04-21 19:02:58 +01004580 } else if (mExternalStylusFusionTimeout != LLONG_MAX) {
4581 getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
Michael Wright842500e2015-03-13 17:32:02 -07004582 }
4583 }
4584}
4585
4586void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
Michael Wright4af18b92015-04-20 22:03:54 +01004587 mExternalStylusState.copyFrom(state);
Michael Wright43fd19f2015-04-21 19:02:58 +01004588 if (mExternalStylusId != -1 || mExternalStylusFusionTimeout != LLONG_MAX) {
Michael Wright842500e2015-03-13 17:32:02 -07004589 // We're either in the middle of a fused stream of data or we're waiting on data before
4590 // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
4591 // data.
Michael Wright842500e2015-03-13 17:32:02 -07004592 mExternalStylusDataPending = true;
Michael Wright842500e2015-03-13 17:32:02 -07004593 processRawTouches(false /*timeout*/);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004594 }
4595}
4596
4597bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
4598 // Check for release of a virtual key.
4599 if (mCurrentVirtualKey.down) {
Michael Wright842500e2015-03-13 17:32:02 -07004600 if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004601 // Pointer went up while virtual key was down.
4602 mCurrentVirtualKey.down = false;
4603 if (!mCurrentVirtualKey.ignored) {
4604#if DEBUG_VIRTUAL_KEYS
4605 ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
4606 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4607#endif
4608 dispatchVirtualKey(when, policyFlags,
4609 AKEY_EVENT_ACTION_UP,
4610 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4611 }
4612 return true;
4613 }
4614
Michael Wright842500e2015-03-13 17:32:02 -07004615 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
4616 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4617 const RawPointerData::Pointer& pointer =
4618 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004619 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4620 if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
4621 // Pointer is still within the space of the virtual key.
4622 return true;
4623 }
4624 }
4625
4626 // Pointer left virtual key area or another pointer also went down.
4627 // Send key cancellation but do not consume the touch yet.
4628 // This is useful when the user swipes through from the virtual key area
4629 // into the main display surface.
4630 mCurrentVirtualKey.down = false;
4631 if (!mCurrentVirtualKey.ignored) {
4632#if DEBUG_VIRTUAL_KEYS
4633 ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
4634 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4635#endif
4636 dispatchVirtualKey(when, policyFlags,
4637 AKEY_EVENT_ACTION_UP,
4638 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4639 | AKEY_EVENT_FLAG_CANCELED);
4640 }
4641 }
4642
Michael Wright842500e2015-03-13 17:32:02 -07004643 if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
4644 && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004645 // Pointer just went down. Check for virtual key press or off-screen touches.
Michael Wright842500e2015-03-13 17:32:02 -07004646 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4647 const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004648 if (!isPointInsideSurface(pointer.x, pointer.y)) {
4649 // If exactly one pointer went down, check for virtual key hit.
4650 // Otherwise we will drop the entire stroke.
Michael Wright842500e2015-03-13 17:32:02 -07004651 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004652 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4653 if (virtualKey) {
4654 mCurrentVirtualKey.down = true;
4655 mCurrentVirtualKey.downTime = when;
4656 mCurrentVirtualKey.keyCode = virtualKey->keyCode;
4657 mCurrentVirtualKey.scanCode = virtualKey->scanCode;
4658 mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
4659 when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
4660
4661 if (!mCurrentVirtualKey.ignored) {
4662#if DEBUG_VIRTUAL_KEYS
4663 ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
4664 mCurrentVirtualKey.keyCode,
4665 mCurrentVirtualKey.scanCode);
4666#endif
4667 dispatchVirtualKey(when, policyFlags,
4668 AKEY_EVENT_ACTION_DOWN,
4669 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4670 }
4671 }
4672 }
4673 return true;
4674 }
4675 }
4676
4677 // Disable all virtual key touches that happen within a short time interval of the
4678 // most recent touch within the screen area. The idea is to filter out stray
4679 // virtual key presses when interacting with the touch screen.
4680 //
4681 // Problems we're trying to solve:
4682 //
4683 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
4684 // virtual key area that is implemented by a separate touch panel and accidentally
4685 // triggers a virtual key.
4686 //
4687 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
4688 // area and accidentally triggers a virtual key. This often happens when virtual keys
4689 // are layed out below the screen near to where the on screen keyboard's space bar
4690 // is displayed.
Michael Wright842500e2015-03-13 17:32:02 -07004691 if (mConfig.virtualKeyQuietTime > 0 &&
4692 !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004693 mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
4694 }
4695 return false;
4696}
4697
4698void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
4699 int32_t keyEventAction, int32_t keyEventFlags) {
4700 int32_t keyCode = mCurrentVirtualKey.keyCode;
4701 int32_t scanCode = mCurrentVirtualKey.scanCode;
4702 nsecs_t downTime = mCurrentVirtualKey.downTime;
4703 int32_t metaState = mContext->getGlobalMetaState();
4704 policyFlags |= POLICY_FLAG_VIRTUAL;
4705
Siarhei Vishniakoua62a8dd2018-06-08 21:17:33 +01004706 NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, mViewport.displayId,
4707 policyFlags, keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004708 getListener()->notifyKey(&args);
4709}
4710
Michael Wright8e812822015-06-22 16:18:21 +01004711void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
4712 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4713 if (!currentIdBits.isEmpty()) {
4714 int32_t metaState = getContext()->getGlobalMetaState();
4715 int32_t buttonState = mCurrentCookedState.buttonState;
4716 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
4717 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004718 mCurrentCookedState.deviceTimestamp,
Michael Wright8e812822015-06-22 16:18:21 +01004719 mCurrentCookedState.cookedPointerData.pointerProperties,
4720 mCurrentCookedState.cookedPointerData.pointerCoords,
4721 mCurrentCookedState.cookedPointerData.idToIndex,
4722 currentIdBits, -1,
4723 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4724 mCurrentMotionAborted = true;
4725 }
4726}
4727
Michael Wrightd02c5b62014-02-10 15:10:22 -08004728void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004729 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4730 BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004731 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01004732 int32_t buttonState = mCurrentCookedState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004733
4734 if (currentIdBits == lastIdBits) {
4735 if (!currentIdBits.isEmpty()) {
4736 // No pointer id changes so this is a move event.
4737 // The listener takes care of batching moves so we don't have to deal with that here.
4738 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004739 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004740 AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004741 mCurrentCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004742 mCurrentCookedState.cookedPointerData.pointerProperties,
4743 mCurrentCookedState.cookedPointerData.pointerCoords,
4744 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004745 currentIdBits, -1,
4746 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4747 }
4748 } else {
4749 // There may be pointers going up and pointers going down and pointers moving
4750 // all at the same time.
4751 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
4752 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
4753 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
4754 BitSet32 dispatchedIdBits(lastIdBits.value);
4755
4756 // Update last coordinates of pointers that have moved so that we observe the new
4757 // pointer positions at the same time as other pointers that have just gone up.
4758 bool moveNeeded = updateMovedPointers(
Michael Wright842500e2015-03-13 17:32:02 -07004759 mCurrentCookedState.cookedPointerData.pointerProperties,
4760 mCurrentCookedState.cookedPointerData.pointerCoords,
4761 mCurrentCookedState.cookedPointerData.idToIndex,
4762 mLastCookedState.cookedPointerData.pointerProperties,
4763 mLastCookedState.cookedPointerData.pointerCoords,
4764 mLastCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004765 moveIdBits);
Michael Wright7b159c92015-05-14 14:48:03 +01004766 if (buttonState != mLastCookedState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004767 moveNeeded = true;
4768 }
4769
4770 // Dispatch pointer up events.
4771 while (!upIdBits.isEmpty()) {
4772 uint32_t upId = upIdBits.clearFirstMarkedBit();
4773
4774 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004775 AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004776 mCurrentCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004777 mLastCookedState.cookedPointerData.pointerProperties,
4778 mLastCookedState.cookedPointerData.pointerCoords,
4779 mLastCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004780 dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004781 dispatchedIdBits.clearBit(upId);
4782 }
4783
4784 // Dispatch move events if any of the remaining pointers moved from their old locations.
4785 // Although applications receive new locations as part of individual pointer up
4786 // events, they do not generally handle them except when presented in a move event.
Michael Wright43fd19f2015-04-21 19:02:58 +01004787 if (moveNeeded && !moveIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004788 ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
4789 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004790 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004791 mCurrentCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004792 mCurrentCookedState.cookedPointerData.pointerProperties,
4793 mCurrentCookedState.cookedPointerData.pointerCoords,
4794 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004795 dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004796 }
4797
4798 // Dispatch pointer down events using the new pointer locations.
4799 while (!downIdBits.isEmpty()) {
4800 uint32_t downId = downIdBits.clearFirstMarkedBit();
4801 dispatchedIdBits.markBit(downId);
4802
4803 if (dispatchedIdBits.count() == 1) {
4804 // First pointer is going down. Set down time.
4805 mDownTime = when;
4806 }
4807
4808 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004809 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004810 mCurrentCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004811 mCurrentCookedState.cookedPointerData.pointerProperties,
4812 mCurrentCookedState.cookedPointerData.pointerCoords,
4813 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01004814 dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004815 }
4816 }
4817}
4818
4819void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
4820 if (mSentHoverEnter &&
Michael Wright842500e2015-03-13 17:32:02 -07004821 (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
4822 || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004823 int32_t metaState = getContext()->getGlobalMetaState();
4824 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004825 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastCookedState.buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004826 mLastCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004827 mLastCookedState.cookedPointerData.pointerProperties,
4828 mLastCookedState.cookedPointerData.pointerCoords,
4829 mLastCookedState.cookedPointerData.idToIndex,
4830 mLastCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004831 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4832 mSentHoverEnter = false;
4833 }
4834}
4835
4836void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004837 if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
4838 && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004839 int32_t metaState = getContext()->getGlobalMetaState();
4840 if (!mSentHoverEnter) {
Michael Wright842500e2015-03-13 17:32:02 -07004841 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
Michael Wright7b159c92015-05-14 14:48:03 +01004842 0, 0, metaState, mCurrentRawState.buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004843 mCurrentCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004844 mCurrentCookedState.cookedPointerData.pointerProperties,
4845 mCurrentCookedState.cookedPointerData.pointerCoords,
4846 mCurrentCookedState.cookedPointerData.idToIndex,
4847 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004848 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4849 mSentHoverEnter = true;
4850 }
4851
4852 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01004853 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
Michael Wright842500e2015-03-13 17:32:02 -07004854 mCurrentRawState.buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004855 mCurrentCookedState.deviceTimestamp,
Michael Wright842500e2015-03-13 17:32:02 -07004856 mCurrentCookedState.cookedPointerData.pointerProperties,
4857 mCurrentCookedState.cookedPointerData.pointerCoords,
4858 mCurrentCookedState.cookedPointerData.idToIndex,
4859 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004860 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4861 }
4862}
4863
Michael Wright7b159c92015-05-14 14:48:03 +01004864void TouchInputMapper::dispatchButtonRelease(nsecs_t when, uint32_t policyFlags) {
4865 BitSet32 releasedButtons(mLastCookedState.buttonState & ~mCurrentCookedState.buttonState);
4866 const BitSet32& idBits = findActiveIdBits(mLastCookedState.cookedPointerData);
4867 const int32_t metaState = getContext()->getGlobalMetaState();
4868 int32_t buttonState = mLastCookedState.buttonState;
4869 while (!releasedButtons.isEmpty()) {
4870 int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
4871 buttonState &= ~actionButton;
4872 dispatchMotion(when, policyFlags, mSource,
4873 AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton,
4874 0, metaState, buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004875 mCurrentCookedState.deviceTimestamp,
Michael Wright7b159c92015-05-14 14:48:03 +01004876 mCurrentCookedState.cookedPointerData.pointerProperties,
4877 mCurrentCookedState.cookedPointerData.pointerCoords,
4878 mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
4879 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4880 }
4881}
4882
4883void TouchInputMapper::dispatchButtonPress(nsecs_t when, uint32_t policyFlags) {
4884 BitSet32 pressedButtons(mCurrentCookedState.buttonState & ~mLastCookedState.buttonState);
4885 const BitSet32& idBits = findActiveIdBits(mCurrentCookedState.cookedPointerData);
4886 const int32_t metaState = getContext()->getGlobalMetaState();
4887 int32_t buttonState = mLastCookedState.buttonState;
4888 while (!pressedButtons.isEmpty()) {
4889 int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
4890 buttonState |= actionButton;
4891 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton,
4892 0, metaState, buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004893 mCurrentCookedState.deviceTimestamp,
Michael Wright7b159c92015-05-14 14:48:03 +01004894 mCurrentCookedState.cookedPointerData.pointerProperties,
4895 mCurrentCookedState.cookedPointerData.pointerCoords,
4896 mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
4897 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4898 }
4899}
4900
4901const BitSet32& TouchInputMapper::findActiveIdBits(const CookedPointerData& cookedPointerData) {
4902 if (!cookedPointerData.touchingIdBits.isEmpty()) {
4903 return cookedPointerData.touchingIdBits;
4904 }
4905 return cookedPointerData.hoveringIdBits;
4906}
4907
Michael Wrightd02c5b62014-02-10 15:10:22 -08004908void TouchInputMapper::cookPointerData() {
Michael Wright842500e2015-03-13 17:32:02 -07004909 uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004910
Michael Wright842500e2015-03-13 17:32:02 -07004911 mCurrentCookedState.cookedPointerData.clear();
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08004912 mCurrentCookedState.deviceTimestamp =
4913 mCurrentRawState.deviceTimestamp;
Michael Wright842500e2015-03-13 17:32:02 -07004914 mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
4915 mCurrentCookedState.cookedPointerData.hoveringIdBits =
4916 mCurrentRawState.rawPointerData.hoveringIdBits;
4917 mCurrentCookedState.cookedPointerData.touchingIdBits =
4918 mCurrentRawState.rawPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004919
Michael Wright7b159c92015-05-14 14:48:03 +01004920 if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
4921 mCurrentCookedState.buttonState = 0;
4922 } else {
4923 mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
4924 }
4925
Michael Wrightd02c5b62014-02-10 15:10:22 -08004926 // Walk through the the active pointers and map device coordinates onto
4927 // surface coordinates and adjust for display orientation.
4928 for (uint32_t i = 0; i < currentPointerCount; i++) {
Michael Wright842500e2015-03-13 17:32:02 -07004929 const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08004930
4931 // Size
4932 float touchMajor, touchMinor, toolMajor, toolMinor, size;
4933 switch (mCalibration.sizeCalibration) {
4934 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
4935 case Calibration::SIZE_CALIBRATION_DIAMETER:
4936 case Calibration::SIZE_CALIBRATION_BOX:
4937 case Calibration::SIZE_CALIBRATION_AREA:
4938 if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
4939 touchMajor = in.touchMajor;
4940 touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
4941 toolMajor = in.toolMajor;
4942 toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
4943 size = mRawPointerAxes.touchMinor.valid
4944 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4945 } else if (mRawPointerAxes.touchMajor.valid) {
4946 toolMajor = touchMajor = in.touchMajor;
4947 toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
4948 ? in.touchMinor : in.touchMajor;
4949 size = mRawPointerAxes.touchMinor.valid
4950 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4951 } else if (mRawPointerAxes.toolMajor.valid) {
4952 touchMajor = toolMajor = in.toolMajor;
4953 touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
4954 ? in.toolMinor : in.toolMajor;
4955 size = mRawPointerAxes.toolMinor.valid
4956 ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
4957 } else {
4958 ALOG_ASSERT(false, "No touch or tool axes. "
4959 "Size calibration should have been resolved to NONE.");
4960 touchMajor = 0;
4961 touchMinor = 0;
4962 toolMajor = 0;
4963 toolMinor = 0;
4964 size = 0;
4965 }
4966
4967 if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
Michael Wright842500e2015-03-13 17:32:02 -07004968 uint32_t touchingCount =
4969 mCurrentRawState.rawPointerData.touchingIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004970 if (touchingCount > 1) {
4971 touchMajor /= touchingCount;
4972 touchMinor /= touchingCount;
4973 toolMajor /= touchingCount;
4974 toolMinor /= touchingCount;
4975 size /= touchingCount;
4976 }
4977 }
4978
4979 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
4980 touchMajor *= mGeometricScale;
4981 touchMinor *= mGeometricScale;
4982 toolMajor *= mGeometricScale;
4983 toolMinor *= mGeometricScale;
4984 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
4985 touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
4986 touchMinor = touchMajor;
4987 toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
4988 toolMinor = toolMajor;
4989 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
4990 touchMinor = touchMajor;
4991 toolMinor = toolMajor;
4992 }
4993
4994 mCalibration.applySizeScaleAndBias(&touchMajor);
4995 mCalibration.applySizeScaleAndBias(&touchMinor);
4996 mCalibration.applySizeScaleAndBias(&toolMajor);
4997 mCalibration.applySizeScaleAndBias(&toolMinor);
4998 size *= mSizeScale;
4999 break;
5000 default:
5001 touchMajor = 0;
5002 touchMinor = 0;
5003 toolMajor = 0;
5004 toolMinor = 0;
5005 size = 0;
5006 break;
5007 }
5008
5009 // Pressure
5010 float pressure;
5011 switch (mCalibration.pressureCalibration) {
5012 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
5013 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
5014 pressure = in.pressure * mPressureScale;
5015 break;
5016 default:
5017 pressure = in.isHovering ? 0 : 1;
5018 break;
5019 }
5020
5021 // Tilt and Orientation
5022 float tilt;
5023 float orientation;
5024 if (mHaveTilt) {
5025 float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
5026 float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
5027 orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
5028 tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
5029 } else {
5030 tilt = 0;
5031
5032 switch (mCalibration.orientationCalibration) {
5033 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
5034 orientation = in.orientation * mOrientationScale;
5035 break;
5036 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
5037 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
5038 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
5039 if (c1 != 0 || c2 != 0) {
5040 orientation = atan2f(c1, c2) * 0.5f;
5041 float confidence = hypotf(c1, c2);
5042 float scale = 1.0f + confidence / 16.0f;
5043 touchMajor *= scale;
5044 touchMinor /= scale;
5045 toolMajor *= scale;
5046 toolMinor /= scale;
5047 } else {
5048 orientation = 0;
5049 }
5050 break;
5051 }
5052 default:
5053 orientation = 0;
5054 }
5055 }
5056
5057 // Distance
5058 float distance;
5059 switch (mCalibration.distanceCalibration) {
5060 case Calibration::DISTANCE_CALIBRATION_SCALED:
5061 distance = in.distance * mDistanceScale;
5062 break;
5063 default:
5064 distance = 0;
5065 }
5066
5067 // Coverage
5068 int32_t rawLeft, rawTop, rawRight, rawBottom;
5069 switch (mCalibration.coverageCalibration) {
5070 case Calibration::COVERAGE_CALIBRATION_BOX:
5071 rawLeft = (in.toolMinor & 0xffff0000) >> 16;
5072 rawRight = in.toolMinor & 0x0000ffff;
5073 rawBottom = in.toolMajor & 0x0000ffff;
5074 rawTop = (in.toolMajor & 0xffff0000) >> 16;
5075 break;
5076 default:
5077 rawLeft = rawTop = rawRight = rawBottom = 0;
5078 break;
5079 }
5080
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005081 // Adjust X,Y coords for device calibration
5082 // TODO: Adjust coverage coords?
5083 float xTransformed = in.x, yTransformed = in.y;
5084 mAffineTransform.applyTo(xTransformed, yTransformed);
5085
5086 // Adjust X, Y, and coverage coords for surface orientation.
5087 float x, y;
5088 float left, top, right, bottom;
5089
Michael Wrightd02c5b62014-02-10 15:10:22 -08005090 switch (mSurfaceOrientation) {
5091 case DISPLAY_ORIENTATION_90:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005092 x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5093 y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005094 left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5095 right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5096 bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
5097 top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
5098 orientation -= M_PI_2;
baik.han18a81482015-04-14 19:49:28 +09005099 if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005100 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5101 }
5102 break;
5103 case DISPLAY_ORIENTATION_180:
Michael Wright358bcc72018-08-21 04:01:07 +01005104 x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale;
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005105 y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
Michael Wright358bcc72018-08-21 04:01:07 +01005106 left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
5107 right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005108 bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
5109 top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
5110 orientation -= M_PI;
baik.han18a81482015-04-14 19:49:28 +09005111 if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005112 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5113 }
5114 break;
5115 case DISPLAY_ORIENTATION_270:
Michael Wright358bcc72018-08-21 04:01:07 +01005116 x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale;
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005117 y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
Michael Wright358bcc72018-08-21 04:01:07 +01005118 left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
5119 right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005120 bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5121 top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5122 orientation += M_PI_2;
baik.han18a81482015-04-14 19:49:28 +09005123 if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005124 orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
5125 }
5126 break;
5127 default:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07005128 x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5129 y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005130 left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5131 right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
5132 bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5133 top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
5134 break;
5135 }
5136
5137 // Write output coords.
Michael Wright842500e2015-03-13 17:32:02 -07005138 PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005139 out.clear();
5140 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5141 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5142 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
5143 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
5144 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
5145 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
5146 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
5147 out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
5148 out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
5149 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
5150 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
5151 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
5152 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
5153 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
5154 } else {
5155 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
5156 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
5157 }
5158
5159 // Write output properties.
Michael Wright842500e2015-03-13 17:32:02 -07005160 PointerProperties& properties =
5161 mCurrentCookedState.cookedPointerData.pointerProperties[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08005162 uint32_t id = in.id;
5163 properties.clear();
5164 properties.id = id;
5165 properties.toolType = in.toolType;
5166
5167 // Write id index.
Michael Wright842500e2015-03-13 17:32:02 -07005168 mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005169 }
5170}
5171
5172void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
5173 PointerUsage pointerUsage) {
5174 if (pointerUsage != mPointerUsage) {
5175 abortPointerUsage(when, policyFlags);
5176 mPointerUsage = pointerUsage;
5177 }
5178
5179 switch (mPointerUsage) {
5180 case POINTER_USAGE_GESTURES:
5181 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
5182 break;
5183 case POINTER_USAGE_STYLUS:
5184 dispatchPointerStylus(when, policyFlags);
5185 break;
5186 case POINTER_USAGE_MOUSE:
5187 dispatchPointerMouse(when, policyFlags);
5188 break;
5189 default:
5190 break;
5191 }
5192}
5193
5194void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
5195 switch (mPointerUsage) {
5196 case POINTER_USAGE_GESTURES:
5197 abortPointerGestures(when, policyFlags);
5198 break;
5199 case POINTER_USAGE_STYLUS:
5200 abortPointerStylus(when, policyFlags);
5201 break;
5202 case POINTER_USAGE_MOUSE:
5203 abortPointerMouse(when, policyFlags);
5204 break;
5205 default:
5206 break;
5207 }
5208
5209 mPointerUsage = POINTER_USAGE_NONE;
5210}
5211
5212void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
5213 bool isTimeout) {
5214 // Update current gesture coordinates.
5215 bool cancelPreviousGesture, finishPreviousGesture;
5216 bool sendEvents = preparePointerGestures(when,
5217 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
5218 if (!sendEvents) {
5219 return;
5220 }
5221 if (finishPreviousGesture) {
5222 cancelPreviousGesture = false;
5223 }
5224
5225 // Update the pointer presentation and spots.
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005226 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
5227 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005228 if (finishPreviousGesture || cancelPreviousGesture) {
5229 mPointerController->clearSpots();
5230 }
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005231
5232 if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
5233 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
5234 mPointerGesture.currentGestureIdToIndex,
5235 mPointerGesture.currentGestureIdBits);
5236 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08005237 } else {
5238 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5239 }
5240
5241 // Show or hide the pointer if needed.
5242 switch (mPointerGesture.currentGestureMode) {
5243 case PointerGesture::NEUTRAL:
5244 case PointerGesture::QUIET:
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005245 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
5246 && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005247 // Remind the user of where the pointer is after finishing a gesture with spots.
5248 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
5249 }
5250 break;
5251 case PointerGesture::TAP:
5252 case PointerGesture::TAP_DRAG:
5253 case PointerGesture::BUTTON_CLICK_OR_DRAG:
5254 case PointerGesture::HOVER:
5255 case PointerGesture::PRESS:
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005256 case PointerGesture::SWIPE:
Michael Wrightd02c5b62014-02-10 15:10:22 -08005257 // Unfade the pointer when the current gesture manipulates the
5258 // area directly under the pointer.
5259 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5260 break;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005261 case PointerGesture::FREEFORM:
5262 // Fade the pointer when the current gesture manipulates a different
5263 // area and there are spots to guide the user experience.
Amirhossein Simjour3dd617b2015-10-09 10:39:48 -04005264 if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005265 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5266 } else {
5267 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5268 }
5269 break;
5270 }
5271
5272 // Send events!
5273 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright7b159c92015-05-14 14:48:03 +01005274 int32_t buttonState = mCurrentCookedState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005275
5276 // Update last coordinates of pointers that have moved so that we observe the new
5277 // pointer positions at the same time as other pointers that have just gone up.
5278 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
5279 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
5280 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5281 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
5282 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
5283 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
5284 bool moveNeeded = false;
5285 if (down && !cancelPreviousGesture && !finishPreviousGesture
5286 && !mPointerGesture.lastGestureIdBits.isEmpty()
5287 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
5288 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
5289 & mPointerGesture.lastGestureIdBits.value);
5290 moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
5291 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5292 mPointerGesture.lastGestureProperties,
5293 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5294 movedGestureIdBits);
Michael Wright7b159c92015-05-14 14:48:03 +01005295 if (buttonState != mLastCookedState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005296 moveNeeded = true;
5297 }
5298 }
5299
5300 // Send motion events for all pointers that went up or were canceled.
5301 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
5302 if (!dispatchedGestureIdBits.isEmpty()) {
5303 if (cancelPreviousGesture) {
5304 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005305 AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08005306 AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005307 mPointerGesture.lastGestureProperties,
5308 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
Michael Wright7b159c92015-05-14 14:48:03 +01005309 dispatchedGestureIdBits, -1, 0,
5310 0, mPointerGesture.downTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005311
5312 dispatchedGestureIdBits.clear();
5313 } else {
5314 BitSet32 upGestureIdBits;
5315 if (finishPreviousGesture) {
5316 upGestureIdBits = dispatchedGestureIdBits;
5317 } else {
5318 upGestureIdBits.value = dispatchedGestureIdBits.value
5319 & ~mPointerGesture.currentGestureIdBits.value;
5320 }
5321 while (!upGestureIdBits.isEmpty()) {
5322 uint32_t id = upGestureIdBits.clearFirstMarkedBit();
5323
5324 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005325 AMOTION_EVENT_ACTION_POINTER_UP, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005326 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08005327 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005328 mPointerGesture.lastGestureProperties,
5329 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5330 dispatchedGestureIdBits, id,
5331 0, 0, mPointerGesture.downTime);
5332
5333 dispatchedGestureIdBits.clearBit(id);
5334 }
5335 }
5336 }
5337
5338 // Send motion events for all pointers that moved.
5339 if (moveNeeded) {
5340 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005341 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08005342 AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005343 mPointerGesture.currentGestureProperties,
5344 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5345 dispatchedGestureIdBits, -1,
5346 0, 0, mPointerGesture.downTime);
5347 }
5348
5349 // Send motion events for all pointers that went down.
5350 if (down) {
5351 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
5352 & ~dispatchedGestureIdBits.value);
5353 while (!downGestureIdBits.isEmpty()) {
5354 uint32_t id = downGestureIdBits.clearFirstMarkedBit();
5355 dispatchedGestureIdBits.markBit(id);
5356
5357 if (dispatchedGestureIdBits.count() == 1) {
5358 mPointerGesture.downTime = when;
5359 }
5360
5361 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005362 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08005363 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005364 mPointerGesture.currentGestureProperties,
5365 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5366 dispatchedGestureIdBits, id,
5367 0, 0, mPointerGesture.downTime);
5368 }
5369 }
5370
5371 // Send motion events for hover.
5372 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
5373 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005374 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08005375 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005376 mPointerGesture.currentGestureProperties,
5377 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
5378 mPointerGesture.currentGestureIdBits, -1,
5379 0, 0, mPointerGesture.downTime);
5380 } else if (dispatchedGestureIdBits.isEmpty()
5381 && !mPointerGesture.lastGestureIdBits.isEmpty()) {
5382 // Synthesize a hover move event after all pointers go up to indicate that
5383 // the pointer is hovering again even if the user is not currently touching
5384 // the touch pad. This ensures that a view will receive a fresh hover enter
5385 // event after a tap.
5386 float x, y;
5387 mPointerController->getPosition(&x, &y);
5388
5389 PointerProperties pointerProperties;
5390 pointerProperties.clear();
5391 pointerProperties.id = 0;
5392 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5393
5394 PointerCoords pointerCoords;
5395 pointerCoords.clear();
5396 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5397 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5398
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08005399 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01005400 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005401 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08005402 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005403 0, 0, mPointerGesture.downTime);
5404 getListener()->notifyMotion(&args);
5405 }
5406
5407 // Update state.
5408 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
5409 if (!down) {
5410 mPointerGesture.lastGestureIdBits.clear();
5411 } else {
5412 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
5413 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
5414 uint32_t id = idBits.clearFirstMarkedBit();
5415 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
5416 mPointerGesture.lastGestureProperties[index].copyFrom(
5417 mPointerGesture.currentGestureProperties[index]);
5418 mPointerGesture.lastGestureCoords[index].copyFrom(
5419 mPointerGesture.currentGestureCoords[index]);
5420 mPointerGesture.lastGestureIdToIndex[id] = index;
5421 }
5422 }
5423}
5424
5425void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
5426 // Cancel previously dispatches pointers.
5427 if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
5428 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright842500e2015-03-13 17:32:02 -07005429 int32_t buttonState = mCurrentRawState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005430 dispatchMotion(when, policyFlags, mSource,
Michael Wright7b159c92015-05-14 14:48:03 +01005431 AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08005432 AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005433 mPointerGesture.lastGestureProperties,
5434 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
5435 mPointerGesture.lastGestureIdBits, -1,
5436 0, 0, mPointerGesture.downTime);
5437 }
5438
5439 // Reset the current pointer gesture.
5440 mPointerGesture.reset();
5441 mPointerVelocityControl.reset();
5442
5443 // Remove any current spots.
Yi Kong9b14ac62018-07-17 13:48:38 -07005444 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005445 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5446 mPointerController->clearSpots();
5447 }
5448}
5449
5450bool TouchInputMapper::preparePointerGestures(nsecs_t when,
5451 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
5452 *outCancelPreviousGesture = false;
5453 *outFinishPreviousGesture = false;
5454
5455 // Handle TAP timeout.
5456 if (isTimeout) {
5457#if DEBUG_GESTURES
5458 ALOGD("Gestures: Processing timeout");
5459#endif
5460
5461 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5462 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5463 // The tap/drag timeout has not yet expired.
5464 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
5465 + mConfig.pointerGestureTapDragInterval);
5466 } else {
5467 // The tap is finished.
5468#if DEBUG_GESTURES
5469 ALOGD("Gestures: TAP finished");
5470#endif
5471 *outFinishPreviousGesture = true;
5472
5473 mPointerGesture.activeGestureId = -1;
5474 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5475 mPointerGesture.currentGestureIdBits.clear();
5476
5477 mPointerVelocityControl.reset();
5478 return true;
5479 }
5480 }
5481
5482 // We did not handle this timeout.
5483 return false;
5484 }
5485
Michael Wright842500e2015-03-13 17:32:02 -07005486 const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
5487 const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005488
5489 // Update the velocity tracker.
5490 {
5491 VelocityTracker::Position positions[MAX_POINTERS];
5492 uint32_t count = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005493 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005494 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005495 const RawPointerData::Pointer& pointer =
5496 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005497 positions[count].x = pointer.x * mPointerXMovementScale;
5498 positions[count].y = pointer.y * mPointerYMovementScale;
5499 }
5500 mPointerGesture.velocityTracker.addMovement(when,
Michael Wright842500e2015-03-13 17:32:02 -07005501 mCurrentCookedState.fingerIdBits, positions);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005502 }
5503
5504 // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
5505 // to NEUTRAL, then we should not generate tap event.
5506 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
5507 && mPointerGesture.lastGestureMode != PointerGesture::TAP
5508 && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
5509 mPointerGesture.resetTap();
5510 }
5511
5512 // Pick a new active touch id if needed.
5513 // Choose an arbitrary pointer that just went down, if there is one.
5514 // Otherwise choose an arbitrary remaining pointer.
5515 // This guarantees we always have an active touch id when there is at least one pointer.
5516 // We keep the same active touch id for as long as possible.
Michael Wrightd02c5b62014-02-10 15:10:22 -08005517 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
5518 int32_t activeTouchId = lastActiveTouchId;
5519 if (activeTouchId < 0) {
Michael Wright842500e2015-03-13 17:32:02 -07005520 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005521 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07005522 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005523 mPointerGesture.firstTouchTime = when;
5524 }
Michael Wright842500e2015-03-13 17:32:02 -07005525 } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wright842500e2015-03-13 17:32:02 -07005526 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005527 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07005528 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005529 } else {
5530 activeTouchId = mPointerGesture.activeTouchId = -1;
5531 }
5532 }
5533
5534 // Determine whether we are in quiet time.
5535 bool isQuietTime = false;
5536 if (activeTouchId < 0) {
5537 mPointerGesture.resetQuietTime();
5538 } else {
5539 isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
5540 if (!isQuietTime) {
5541 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
5542 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
5543 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
5544 && currentFingerCount < 2) {
5545 // Enter quiet time when exiting swipe or freeform state.
5546 // This is to prevent accidentally entering the hover state and flinging the
5547 // pointer when finishing a swipe and there is still one pointer left onscreen.
5548 isQuietTime = true;
5549 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5550 && currentFingerCount >= 2
Michael Wright842500e2015-03-13 17:32:02 -07005551 && !isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005552 // Enter quiet time when releasing the button and there are still two or more
5553 // fingers down. This may indicate that one finger was used to press the button
5554 // but it has not gone up yet.
5555 isQuietTime = true;
5556 }
5557 if (isQuietTime) {
5558 mPointerGesture.quietTime = when;
5559 }
5560 }
5561 }
5562
5563 // Switch states based on button and pointer state.
5564 if (isQuietTime) {
5565 // Case 1: Quiet time. (QUIET)
5566#if DEBUG_GESTURES
5567 ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
5568 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
5569#endif
5570 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
5571 *outFinishPreviousGesture = true;
5572 }
5573
5574 mPointerGesture.activeGestureId = -1;
5575 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
5576 mPointerGesture.currentGestureIdBits.clear();
5577
5578 mPointerVelocityControl.reset();
Michael Wright842500e2015-03-13 17:32:02 -07005579 } else if (isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005580 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
5581 // The pointer follows the active touch point.
5582 // Emit DOWN, MOVE, UP events at the pointer location.
5583 //
5584 // Only the active touch matters; other fingers are ignored. This policy helps
5585 // to handle the case where the user places a second finger on the touch pad
5586 // to apply the necessary force to depress an integrated button below the surface.
5587 // We don't want the second finger to be delivered to applications.
5588 //
5589 // For this to work well, we need to make sure to track the pointer that is really
5590 // active. If the user first puts one finger down to click then adds another
5591 // finger to drag then the active pointer should switch to the finger that is
5592 // being dragged.
5593#if DEBUG_GESTURES
5594 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
5595 "currentFingerCount=%d", activeTouchId, currentFingerCount);
5596#endif
5597 // Reset state when just starting.
5598 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
5599 *outFinishPreviousGesture = true;
5600 mPointerGesture.activeGestureId = 0;
5601 }
5602
5603 // Switch pointers if needed.
5604 // Find the fastest pointer and follow it.
5605 if (activeTouchId >= 0 && currentFingerCount > 1) {
5606 int32_t bestId = -1;
5607 float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
Michael Wright842500e2015-03-13 17:32:02 -07005608 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005609 uint32_t id = idBits.clearFirstMarkedBit();
5610 float vx, vy;
5611 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
5612 float speed = hypotf(vx, vy);
5613 if (speed > bestSpeed) {
5614 bestId = id;
5615 bestSpeed = speed;
5616 }
5617 }
5618 }
5619 if (bestId >= 0 && bestId != activeTouchId) {
5620 mPointerGesture.activeTouchId = activeTouchId = bestId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005621#if DEBUG_GESTURES
5622 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
5623 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
5624#endif
5625 }
5626 }
5627
Jun Mukaifa1706a2015-12-03 01:14:46 -08005628 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005629 if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005630 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005631 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005632 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005633 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Jun Mukaifa1706a2015-12-03 01:14:46 -08005634 deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5635 deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005636
5637 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5638 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5639
5640 // Move the pointer using a relative motion.
5641 // When using spots, the click will occur at the position of the anchor
5642 // spot and all other spots will move there.
5643 mPointerController->move(deltaX, deltaY);
5644 } else {
5645 mPointerVelocityControl.reset();
5646 }
5647
5648 float x, y;
5649 mPointerController->getPosition(&x, &y);
5650
5651 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
5652 mPointerGesture.currentGestureIdBits.clear();
5653 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5654 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5655 mPointerGesture.currentGestureProperties[0].clear();
5656 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5657 mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5658 mPointerGesture.currentGestureCoords[0].clear();
5659 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5660 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5661 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5662 } else if (currentFingerCount == 0) {
5663 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
5664 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
5665 *outFinishPreviousGesture = true;
5666 }
5667
5668 // Watch for taps coming out of HOVER or TAP_DRAG mode.
5669 // Checking for taps after TAP_DRAG allows us to detect double-taps.
5670 bool tapped = false;
5671 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
5672 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
5673 && lastFingerCount == 1) {
5674 if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
5675 float x, y;
5676 mPointerController->getPosition(&x, &y);
5677 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5678 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5679#if DEBUG_GESTURES
5680 ALOGD("Gestures: TAP");
5681#endif
5682
5683 mPointerGesture.tapUpTime = when;
5684 getContext()->requestTimeoutAtTime(when
5685 + mConfig.pointerGestureTapDragInterval);
5686
5687 mPointerGesture.activeGestureId = 0;
5688 mPointerGesture.currentGestureMode = PointerGesture::TAP;
5689 mPointerGesture.currentGestureIdBits.clear();
5690 mPointerGesture.currentGestureIdBits.markBit(
5691 mPointerGesture.activeGestureId);
5692 mPointerGesture.currentGestureIdToIndex[
5693 mPointerGesture.activeGestureId] = 0;
5694 mPointerGesture.currentGestureProperties[0].clear();
5695 mPointerGesture.currentGestureProperties[0].id =
5696 mPointerGesture.activeGestureId;
5697 mPointerGesture.currentGestureProperties[0].toolType =
5698 AMOTION_EVENT_TOOL_TYPE_FINGER;
5699 mPointerGesture.currentGestureCoords[0].clear();
5700 mPointerGesture.currentGestureCoords[0].setAxisValue(
5701 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
5702 mPointerGesture.currentGestureCoords[0].setAxisValue(
5703 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
5704 mPointerGesture.currentGestureCoords[0].setAxisValue(
5705 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5706
5707 tapped = true;
5708 } else {
5709#if DEBUG_GESTURES
5710 ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
5711 x - mPointerGesture.tapX,
5712 y - mPointerGesture.tapY);
5713#endif
5714 }
5715 } else {
5716#if DEBUG_GESTURES
5717 if (mPointerGesture.tapDownTime != LLONG_MIN) {
5718 ALOGD("Gestures: Not a TAP, %0.3fms since down",
5719 (when - mPointerGesture.tapDownTime) * 0.000001f);
5720 } else {
5721 ALOGD("Gestures: Not a TAP, incompatible mode transitions");
5722 }
5723#endif
5724 }
5725 }
5726
5727 mPointerVelocityControl.reset();
5728
5729 if (!tapped) {
5730#if DEBUG_GESTURES
5731 ALOGD("Gestures: NEUTRAL");
5732#endif
5733 mPointerGesture.activeGestureId = -1;
5734 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5735 mPointerGesture.currentGestureIdBits.clear();
5736 }
5737 } else if (currentFingerCount == 1) {
5738 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
5739 // The pointer follows the active touch point.
5740 // When in HOVER, emit HOVER_MOVE events at the pointer location.
5741 // When in TAP_DRAG, emit MOVE events at the pointer location.
5742 ALOG_ASSERT(activeTouchId >= 0);
5743
5744 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
5745 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5746 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5747 float x, y;
5748 mPointerController->getPosition(&x, &y);
5749 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5750 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5751 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5752 } else {
5753#if DEBUG_GESTURES
5754 ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
5755 x - mPointerGesture.tapX,
5756 y - mPointerGesture.tapY);
5757#endif
5758 }
5759 } else {
5760#if DEBUG_GESTURES
5761 ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
5762 (when - mPointerGesture.tapUpTime) * 0.000001f);
5763#endif
5764 }
5765 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
5766 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5767 }
5768
Jun Mukaifa1706a2015-12-03 01:14:46 -08005769 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005770 if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005771 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005772 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005773 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005774 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Jun Mukaifa1706a2015-12-03 01:14:46 -08005775 deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5776 deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005777
5778 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5779 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5780
5781 // Move the pointer using a relative motion.
5782 // When using spots, the hover or drag will occur at the position of the anchor spot.
5783 mPointerController->move(deltaX, deltaY);
5784 } else {
5785 mPointerVelocityControl.reset();
5786 }
5787
5788 bool down;
5789 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
5790#if DEBUG_GESTURES
5791 ALOGD("Gestures: TAP_DRAG");
5792#endif
5793 down = true;
5794 } else {
5795#if DEBUG_GESTURES
5796 ALOGD("Gestures: HOVER");
5797#endif
5798 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
5799 *outFinishPreviousGesture = true;
5800 }
5801 mPointerGesture.activeGestureId = 0;
5802 down = false;
5803 }
5804
5805 float x, y;
5806 mPointerController->getPosition(&x, &y);
5807
5808 mPointerGesture.currentGestureIdBits.clear();
5809 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5810 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5811 mPointerGesture.currentGestureProperties[0].clear();
5812 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5813 mPointerGesture.currentGestureProperties[0].toolType =
5814 AMOTION_EVENT_TOOL_TYPE_FINGER;
5815 mPointerGesture.currentGestureCoords[0].clear();
5816 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5817 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5818 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5819 down ? 1.0f : 0.0f);
5820
5821 if (lastFingerCount == 0 && currentFingerCount != 0) {
5822 mPointerGesture.resetTap();
5823 mPointerGesture.tapDownTime = when;
5824 mPointerGesture.tapX = x;
5825 mPointerGesture.tapY = y;
5826 }
5827 } else {
5828 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
5829 // We need to provide feedback for each finger that goes down so we cannot wait
5830 // for the fingers to move before deciding what to do.
5831 //
5832 // The ambiguous case is deciding what to do when there are two fingers down but they
5833 // have not moved enough to determine whether they are part of a drag or part of a
5834 // freeform gesture, or just a press or long-press at the pointer location.
5835 //
5836 // When there are two fingers we start with the PRESS hypothesis and we generate a
5837 // down at the pointer location.
5838 //
5839 // When the two fingers move enough or when additional fingers are added, we make
5840 // a decision to transition into SWIPE or FREEFORM mode accordingly.
5841 ALOG_ASSERT(activeTouchId >= 0);
5842
5843 bool settled = when >= mPointerGesture.firstTouchTime
5844 + mConfig.pointerGestureMultitouchSettleInterval;
5845 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
5846 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
5847 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5848 *outFinishPreviousGesture = true;
5849 } else if (!settled && currentFingerCount > lastFingerCount) {
5850 // Additional pointers have gone down but not yet settled.
5851 // Reset the gesture.
5852#if DEBUG_GESTURES
5853 ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
5854 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5855 + mConfig.pointerGestureMultitouchSettleInterval - when)
5856 * 0.000001f);
5857#endif
5858 *outCancelPreviousGesture = true;
5859 } else {
5860 // Continue previous gesture.
5861 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
5862 }
5863
5864 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
5865 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
5866 mPointerGesture.activeGestureId = 0;
5867 mPointerGesture.referenceIdBits.clear();
5868 mPointerVelocityControl.reset();
5869
5870 // Use the centroid and pointer location as the reference points for the gesture.
5871#if DEBUG_GESTURES
5872 ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
5873 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5874 + mConfig.pointerGestureMultitouchSettleInterval - when)
5875 * 0.000001f);
5876#endif
Michael Wright842500e2015-03-13 17:32:02 -07005877 mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
Michael Wrightd02c5b62014-02-10 15:10:22 -08005878 &mPointerGesture.referenceTouchX,
5879 &mPointerGesture.referenceTouchY);
5880 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
5881 &mPointerGesture.referenceGestureY);
5882 }
5883
5884 // Clear the reference deltas for fingers not yet included in the reference calculation.
Michael Wright842500e2015-03-13 17:32:02 -07005885 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
Michael Wrightd02c5b62014-02-10 15:10:22 -08005886 & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
5887 uint32_t id = idBits.clearFirstMarkedBit();
5888 mPointerGesture.referenceDeltas[id].dx = 0;
5889 mPointerGesture.referenceDeltas[id].dy = 0;
5890 }
Michael Wright842500e2015-03-13 17:32:02 -07005891 mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005892
5893 // Add delta for all fingers and calculate a common movement delta.
5894 float commonDeltaX = 0, commonDeltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005895 BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
5896 & mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005897 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
5898 bool first = (idBits == commonIdBits);
5899 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005900 const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
5901 const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005902 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5903 delta.dx += cpd.x - lpd.x;
5904 delta.dy += cpd.y - lpd.y;
5905
5906 if (first) {
5907 commonDeltaX = delta.dx;
5908 commonDeltaY = delta.dy;
5909 } else {
5910 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
5911 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
5912 }
5913 }
5914
5915 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
5916 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
5917 float dist[MAX_POINTER_ID + 1];
5918 int32_t distOverThreshold = 0;
5919 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
5920 uint32_t id = idBits.clearFirstMarkedBit();
5921 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5922 dist[id] = hypotf(delta.dx * mPointerXZoomScale,
5923 delta.dy * mPointerYZoomScale);
5924 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
5925 distOverThreshold += 1;
5926 }
5927 }
5928
5929 // Only transition when at least two pointers have moved further than
5930 // the minimum distance threshold.
5931 if (distOverThreshold >= 2) {
5932 if (currentFingerCount > 2) {
5933 // There are more than two pointers, switch to FREEFORM.
5934#if DEBUG_GESTURES
5935 ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
5936 currentFingerCount);
5937#endif
5938 *outCancelPreviousGesture = true;
5939 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5940 } else {
5941 // There are exactly two pointers.
Michael Wright842500e2015-03-13 17:32:02 -07005942 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005943 uint32_t id1 = idBits.clearFirstMarkedBit();
5944 uint32_t id2 = idBits.firstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005945 const RawPointerData::Pointer& p1 =
5946 mCurrentRawState.rawPointerData.pointerForId(id1);
5947 const RawPointerData::Pointer& p2 =
5948 mCurrentRawState.rawPointerData.pointerForId(id2);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005949 float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
5950 if (mutualDistance > mPointerGestureMaxSwipeWidth) {
5951 // There are two pointers but they are too far apart for a SWIPE,
5952 // switch to FREEFORM.
5953#if DEBUG_GESTURES
5954 ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
5955 mutualDistance, mPointerGestureMaxSwipeWidth);
5956#endif
5957 *outCancelPreviousGesture = true;
5958 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5959 } else {
5960 // There are two pointers. Wait for both pointers to start moving
5961 // before deciding whether this is a SWIPE or FREEFORM gesture.
5962 float dist1 = dist[id1];
5963 float dist2 = dist[id2];
5964 if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
5965 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
5966 // Calculate the dot product of the displacement vectors.
5967 // When the vectors are oriented in approximately the same direction,
5968 // the angle betweeen them is near zero and the cosine of the angle
5969 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
5970 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
5971 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
5972 float dx1 = delta1.dx * mPointerXZoomScale;
5973 float dy1 = delta1.dy * mPointerYZoomScale;
5974 float dx2 = delta2.dx * mPointerXZoomScale;
5975 float dy2 = delta2.dy * mPointerYZoomScale;
5976 float dot = dx1 * dx2 + dy1 * dy2;
5977 float cosine = dot / (dist1 * dist2); // denominator always > 0
5978 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
5979 // Pointers are moving in the same direction. Switch to SWIPE.
5980#if DEBUG_GESTURES
5981 ALOGD("Gestures: PRESS transitioned to SWIPE, "
5982 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
5983 "cosine %0.3f >= %0.3f",
5984 dist1, mConfig.pointerGestureMultitouchMinDistance,
5985 dist2, mConfig.pointerGestureMultitouchMinDistance,
5986 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
5987#endif
5988 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
5989 } else {
5990 // Pointers are moving in different directions. Switch to FREEFORM.
5991#if DEBUG_GESTURES
5992 ALOGD("Gestures: PRESS transitioned to FREEFORM, "
5993 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
5994 "cosine %0.3f < %0.3f",
5995 dist1, mConfig.pointerGestureMultitouchMinDistance,
5996 dist2, mConfig.pointerGestureMultitouchMinDistance,
5997 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
5998#endif
5999 *outCancelPreviousGesture = true;
6000 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6001 }
6002 }
6003 }
6004 }
6005 }
6006 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
6007 // Switch from SWIPE to FREEFORM if additional pointers go down.
6008 // Cancel previous gesture.
6009 if (currentFingerCount > 2) {
6010#if DEBUG_GESTURES
6011 ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
6012 currentFingerCount);
6013#endif
6014 *outCancelPreviousGesture = true;
6015 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
6016 }
6017 }
6018
6019 // Move the reference points based on the overall group motion of the fingers
6020 // except in PRESS mode while waiting for a transition to occur.
6021 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
6022 && (commonDeltaX || commonDeltaY)) {
6023 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
6024 uint32_t id = idBits.clearFirstMarkedBit();
6025 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
6026 delta.dx = 0;
6027 delta.dy = 0;
6028 }
6029
6030 mPointerGesture.referenceTouchX += commonDeltaX;
6031 mPointerGesture.referenceTouchY += commonDeltaY;
6032
6033 commonDeltaX *= mPointerXMovementScale;
6034 commonDeltaY *= mPointerYMovementScale;
6035
6036 rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
6037 mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
6038
6039 mPointerGesture.referenceGestureX += commonDeltaX;
6040 mPointerGesture.referenceGestureY += commonDeltaY;
6041 }
6042
6043 // Report gestures.
6044 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
6045 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
6046 // PRESS or SWIPE mode.
6047#if DEBUG_GESTURES
6048 ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
6049 "activeGestureId=%d, currentTouchPointerCount=%d",
6050 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
6051#endif
6052 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
6053
6054 mPointerGesture.currentGestureIdBits.clear();
6055 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
6056 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
6057 mPointerGesture.currentGestureProperties[0].clear();
6058 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
6059 mPointerGesture.currentGestureProperties[0].toolType =
6060 AMOTION_EVENT_TOOL_TYPE_FINGER;
6061 mPointerGesture.currentGestureCoords[0].clear();
6062 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
6063 mPointerGesture.referenceGestureX);
6064 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
6065 mPointerGesture.referenceGestureY);
6066 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
6067 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
6068 // FREEFORM mode.
6069#if DEBUG_GESTURES
6070 ALOGD("Gestures: FREEFORM 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
6078 BitSet32 mappedTouchIdBits;
6079 BitSet32 usedGestureIdBits;
6080 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
6081 // Initially, assign the active gesture id to the active touch point
6082 // if there is one. No other touch id bits are mapped yet.
6083 if (!*outCancelPreviousGesture) {
6084 mappedTouchIdBits.markBit(activeTouchId);
6085 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
6086 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
6087 mPointerGesture.activeGestureId;
6088 } else {
6089 mPointerGesture.activeGestureId = -1;
6090 }
6091 } else {
6092 // Otherwise, assume we mapped all touches from the previous frame.
6093 // Reuse all mappings that are still applicable.
Michael Wright842500e2015-03-13 17:32:02 -07006094 mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
6095 & mCurrentCookedState.fingerIdBits.value;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006096 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
6097
6098 // Check whether we need to choose a new active gesture id because the
6099 // current went went up.
Michael Wright842500e2015-03-13 17:32:02 -07006100 for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
6101 & ~mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006102 !upTouchIdBits.isEmpty(); ) {
6103 uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
6104 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
6105 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
6106 mPointerGesture.activeGestureId = -1;
6107 break;
6108 }
6109 }
6110 }
6111
6112#if DEBUG_GESTURES
6113 ALOGD("Gestures: FREEFORM follow up "
6114 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
6115 "activeGestureId=%d",
6116 mappedTouchIdBits.value, usedGestureIdBits.value,
6117 mPointerGesture.activeGestureId);
6118#endif
6119
Michael Wright842500e2015-03-13 17:32:02 -07006120 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006121 for (uint32_t i = 0; i < currentFingerCount; i++) {
6122 uint32_t touchId = idBits.clearFirstMarkedBit();
6123 uint32_t gestureId;
6124 if (!mappedTouchIdBits.hasBit(touchId)) {
6125 gestureId = usedGestureIdBits.markFirstUnmarkedBit();
6126 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
6127#if DEBUG_GESTURES
6128 ALOGD("Gestures: FREEFORM "
6129 "new mapping for touch id %d -> gesture id %d",
6130 touchId, gestureId);
6131#endif
6132 } else {
6133 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
6134#if DEBUG_GESTURES
6135 ALOGD("Gestures: FREEFORM "
6136 "existing mapping for touch id %d -> gesture id %d",
6137 touchId, gestureId);
6138#endif
6139 }
6140 mPointerGesture.currentGestureIdBits.markBit(gestureId);
6141 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
6142
6143 const RawPointerData::Pointer& pointer =
Michael Wright842500e2015-03-13 17:32:02 -07006144 mCurrentRawState.rawPointerData.pointerForId(touchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006145 float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
6146 * mPointerXZoomScale;
6147 float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
6148 * mPointerYZoomScale;
6149 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
6150
6151 mPointerGesture.currentGestureProperties[i].clear();
6152 mPointerGesture.currentGestureProperties[i].id = gestureId;
6153 mPointerGesture.currentGestureProperties[i].toolType =
6154 AMOTION_EVENT_TOOL_TYPE_FINGER;
6155 mPointerGesture.currentGestureCoords[i].clear();
6156 mPointerGesture.currentGestureCoords[i].setAxisValue(
6157 AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
6158 mPointerGesture.currentGestureCoords[i].setAxisValue(
6159 AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
6160 mPointerGesture.currentGestureCoords[i].setAxisValue(
6161 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
6162 }
6163
6164 if (mPointerGesture.activeGestureId < 0) {
6165 mPointerGesture.activeGestureId =
6166 mPointerGesture.currentGestureIdBits.firstMarkedBit();
6167#if DEBUG_GESTURES
6168 ALOGD("Gestures: FREEFORM new "
6169 "activeGestureId=%d", mPointerGesture.activeGestureId);
6170#endif
6171 }
6172 }
6173 }
6174
Michael Wright842500e2015-03-13 17:32:02 -07006175 mPointerController->setButtonState(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006176
6177#if DEBUG_GESTURES
6178 ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
6179 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
6180 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
6181 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
6182 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
6183 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
6184 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
6185 uint32_t id = idBits.clearFirstMarkedBit();
6186 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
6187 const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
6188 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
6189 ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
6190 "x=%0.3f, y=%0.3f, pressure=%0.3f",
6191 id, index, properties.toolType,
6192 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
6193 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
6194 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
6195 }
6196 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
6197 uint32_t id = idBits.clearFirstMarkedBit();
6198 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
6199 const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
6200 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
6201 ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
6202 "x=%0.3f, y=%0.3f, pressure=%0.3f",
6203 id, index, properties.toolType,
6204 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
6205 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
6206 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
6207 }
6208#endif
6209 return true;
6210}
6211
6212void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
6213 mPointerSimple.currentCoords.clear();
6214 mPointerSimple.currentProperties.clear();
6215
6216 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07006217 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
6218 uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
6219 uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
6220 float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
6221 float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006222 mPointerController->setPosition(x, y);
6223
Michael Wright842500e2015-03-13 17:32:02 -07006224 hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006225 down = !hovering;
6226
6227 mPointerController->getPosition(&x, &y);
Michael Wright842500e2015-03-13 17:32:02 -07006228 mPointerSimple.currentCoords.copyFrom(
6229 mCurrentCookedState.cookedPointerData.pointerCoords[index]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006230 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
6231 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
6232 mPointerSimple.currentProperties.id = 0;
6233 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07006234 mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006235 } else {
6236 down = false;
6237 hovering = false;
6238 }
6239
6240 dispatchPointerSimple(when, policyFlags, down, hovering);
6241}
6242
6243void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
6244 abortPointerSimple(when, policyFlags);
6245}
6246
6247void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
6248 mPointerSimple.currentCoords.clear();
6249 mPointerSimple.currentProperties.clear();
6250
6251 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07006252 if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
6253 uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
6254 uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
Jun Mukaifa1706a2015-12-03 01:14:46 -08006255 float deltaX = 0, deltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07006256 if (mLastCookedState.mouseIdBits.hasBit(id)) {
6257 uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
Jun Mukaifa1706a2015-12-03 01:14:46 -08006258 deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
Michael Wright842500e2015-03-13 17:32:02 -07006259 - mLastRawState.rawPointerData.pointers[lastIndex].x)
Michael Wrightd02c5b62014-02-10 15:10:22 -08006260 * mPointerXMovementScale;
Jun Mukaifa1706a2015-12-03 01:14:46 -08006261 deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
Michael Wright842500e2015-03-13 17:32:02 -07006262 - mLastRawState.rawPointerData.pointers[lastIndex].y)
Michael Wrightd02c5b62014-02-10 15:10:22 -08006263 * mPointerYMovementScale;
6264
6265 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
6266 mPointerVelocityControl.move(when, &deltaX, &deltaY);
6267
6268 mPointerController->move(deltaX, deltaY);
6269 } else {
6270 mPointerVelocityControl.reset();
6271 }
6272
Michael Wright842500e2015-03-13 17:32:02 -07006273 down = isPointerDown(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006274 hovering = !down;
6275
6276 float x, y;
6277 mPointerController->getPosition(&x, &y);
6278 mPointerSimple.currentCoords.copyFrom(
Michael Wright842500e2015-03-13 17:32:02 -07006279 mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006280 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
6281 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
6282 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
6283 hovering ? 0.0f : 1.0f);
6284 mPointerSimple.currentProperties.id = 0;
6285 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07006286 mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006287 } else {
6288 mPointerVelocityControl.reset();
6289
6290 down = false;
6291 hovering = false;
6292 }
6293
6294 dispatchPointerSimple(when, policyFlags, down, hovering);
6295}
6296
6297void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
6298 abortPointerSimple(when, policyFlags);
6299
6300 mPointerVelocityControl.reset();
6301}
6302
6303void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
6304 bool down, bool hovering) {
6305 int32_t metaState = getContext()->getGlobalMetaState();
6306
Yi Kong9b14ac62018-07-17 13:48:38 -07006307 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006308 if (down || hovering) {
6309 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
6310 mPointerController->clearSpots();
Michael Wright842500e2015-03-13 17:32:02 -07006311 mPointerController->setButtonState(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006312 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
6313 } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
6314 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
6315 }
6316 }
6317
6318 if (mPointerSimple.down && !down) {
6319 mPointerSimple.down = false;
6320
6321 // Send up.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006322 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006323 AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006324 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006325 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
6326 mOrientedXPrecision, mOrientedYPrecision,
6327 mPointerSimple.downTime);
6328 getListener()->notifyMotion(&args);
6329 }
6330
6331 if (mPointerSimple.hovering && !hovering) {
6332 mPointerSimple.hovering = false;
6333
6334 // Send hover exit.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006335 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006336 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006337 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006338 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
6339 mOrientedXPrecision, mOrientedYPrecision,
6340 mPointerSimple.downTime);
6341 getListener()->notifyMotion(&args);
6342 }
6343
6344 if (down) {
6345 if (!mPointerSimple.down) {
6346 mPointerSimple.down = true;
6347 mPointerSimple.downTime = when;
6348
6349 // Send down.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006350 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006351 AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006352 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006353 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6354 mOrientedXPrecision, mOrientedYPrecision,
6355 mPointerSimple.downTime);
6356 getListener()->notifyMotion(&args);
6357 }
6358
6359 // Send move.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006360 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006361 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006362 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006363 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6364 mOrientedXPrecision, mOrientedYPrecision,
6365 mPointerSimple.downTime);
6366 getListener()->notifyMotion(&args);
6367 }
6368
6369 if (hovering) {
6370 if (!mPointerSimple.hovering) {
6371 mPointerSimple.hovering = true;
6372
6373 // Send hover enter.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006374 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006375 AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
Michael Wright842500e2015-03-13 17:32:02 -07006376 mCurrentRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006377 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006378 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6379 mOrientedXPrecision, mOrientedYPrecision,
6380 mPointerSimple.downTime);
6381 getListener()->notifyMotion(&args);
6382 }
6383
6384 // Send hover move.
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006385 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006386 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
Michael Wright842500e2015-03-13 17:32:02 -07006387 mCurrentRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006388 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006389 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
6390 mOrientedXPrecision, mOrientedYPrecision,
6391 mPointerSimple.downTime);
6392 getListener()->notifyMotion(&args);
6393 }
6394
Michael Wright842500e2015-03-13 17:32:02 -07006395 if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
6396 float vscroll = mCurrentRawState.rawVScroll;
6397 float hscroll = mCurrentRawState.rawHScroll;
Yi Kong9b14ac62018-07-17 13:48:38 -07006398 mWheelYVelocityControl.move(when, nullptr, &vscroll);
6399 mWheelXVelocityControl.move(when, &hscroll, nullptr);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006400
6401 // Send scroll.
6402 PointerCoords pointerCoords;
6403 pointerCoords.copyFrom(mPointerSimple.currentCoords);
6404 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
6405 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
6406
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006407 NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006408 AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006409 /* deviceTimestamp */ 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006410 1, &mPointerSimple.currentProperties, &pointerCoords,
6411 mOrientedXPrecision, mOrientedYPrecision,
6412 mPointerSimple.downTime);
6413 getListener()->notifyMotion(&args);
6414 }
6415
6416 // Save state.
6417 if (down || hovering) {
6418 mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
6419 mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
6420 } else {
6421 mPointerSimple.reset();
6422 }
6423}
6424
6425void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
6426 mPointerSimple.currentCoords.clear();
6427 mPointerSimple.currentProperties.clear();
6428
6429 dispatchPointerSimple(when, policyFlags, false, false);
6430}
6431
6432void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
Michael Wright7b159c92015-05-14 14:48:03 +01006433 int32_t action, int32_t actionButton, int32_t flags,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08006434 int32_t metaState, int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006435 const PointerProperties* properties, const PointerCoords* coords,
Michael Wright7b159c92015-05-14 14:48:03 +01006436 const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
6437 float xPrecision, float yPrecision, nsecs_t downTime) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006438 PointerCoords pointerCoords[MAX_POINTERS];
6439 PointerProperties pointerProperties[MAX_POINTERS];
6440 uint32_t pointerCount = 0;
6441 while (!idBits.isEmpty()) {
6442 uint32_t id = idBits.clearFirstMarkedBit();
6443 uint32_t index = idToIndex[id];
6444 pointerProperties[pointerCount].copyFrom(properties[index]);
6445 pointerCoords[pointerCount].copyFrom(coords[index]);
6446
6447 if (changedId >= 0 && id == uint32_t(changedId)) {
6448 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
6449 }
6450
6451 pointerCount += 1;
6452 }
6453
6454 ALOG_ASSERT(pointerCount != 0);
6455
6456 if (changedId >= 0 && pointerCount == 1) {
6457 // Replace initial down and final up action.
6458 // We can compare the action without masking off the changed pointer index
6459 // because we know the index is 0.
6460 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
6461 action = AMOTION_EVENT_ACTION_DOWN;
6462 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
6463 action = AMOTION_EVENT_ACTION_UP;
6464 } else {
6465 // Can't happen.
6466 ALOG_ASSERT(false);
6467 }
6468 }
6469
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006470 NotifyMotionArgs args(when, getDeviceId(), source, mViewport.displayId, policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01006471 action, actionButton, flags, metaState, buttonState, edgeFlags,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08006472 deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006473 xPrecision, yPrecision, downTime);
6474 getListener()->notifyMotion(&args);
6475}
6476
6477bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
6478 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
6479 PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
6480 BitSet32 idBits) const {
6481 bool changed = false;
6482 while (!idBits.isEmpty()) {
6483 uint32_t id = idBits.clearFirstMarkedBit();
6484 uint32_t inIndex = inIdToIndex[id];
6485 uint32_t outIndex = outIdToIndex[id];
6486
6487 const PointerProperties& curInProperties = inProperties[inIndex];
6488 const PointerCoords& curInCoords = inCoords[inIndex];
6489 PointerProperties& curOutProperties = outProperties[outIndex];
6490 PointerCoords& curOutCoords = outCoords[outIndex];
6491
6492 if (curInProperties != curOutProperties) {
6493 curOutProperties.copyFrom(curInProperties);
6494 changed = true;
6495 }
6496
6497 if (curInCoords != curOutCoords) {
6498 curOutCoords.copyFrom(curInCoords);
6499 changed = true;
6500 }
6501 }
6502 return changed;
6503}
6504
6505void TouchInputMapper::fadePointer() {
Yi Kong9b14ac62018-07-17 13:48:38 -07006506 if (mPointerController != nullptr) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006507 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
6508 }
6509}
6510
Jeff Brownc9aa6282015-02-11 19:03:28 -08006511void TouchInputMapper::cancelTouch(nsecs_t when) {
6512 abortPointerUsage(when, 0 /*policyFlags*/);
Michael Wright8e812822015-06-22 16:18:21 +01006513 abortTouches(when, 0 /* policyFlags*/);
Jeff Brownc9aa6282015-02-11 19:03:28 -08006514}
6515
Michael Wrightd02c5b62014-02-10 15:10:22 -08006516bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
Michael Wright358bcc72018-08-21 04:01:07 +01006517 const float scaledX = x * mXScale;
Michael Wrightc597d612018-08-22 13:49:32 +01006518 const float scaledY = y * mYScale;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006519 return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
Michael Wright358bcc72018-08-21 04:01:07 +01006520 && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth
6521 && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue
6522 && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006523}
6524
6525const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
6526 int32_t x, int32_t y) {
6527 size_t numVirtualKeys = mVirtualKeys.size();
6528 for (size_t i = 0; i < numVirtualKeys; i++) {
6529 const VirtualKey& virtualKey = mVirtualKeys[i];
6530
6531#if DEBUG_VIRTUAL_KEYS
6532 ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
6533 "left=%d, top=%d, right=%d, bottom=%d",
6534 x, y,
6535 virtualKey.keyCode, virtualKey.scanCode,
6536 virtualKey.hitLeft, virtualKey.hitTop,
6537 virtualKey.hitRight, virtualKey.hitBottom);
6538#endif
6539
6540 if (virtualKey.isHit(x, y)) {
6541 return & virtualKey;
6542 }
6543 }
6544
Yi Kong9b14ac62018-07-17 13:48:38 -07006545 return nullptr;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006546}
6547
Michael Wright842500e2015-03-13 17:32:02 -07006548void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
6549 uint32_t currentPointerCount = current->rawPointerData.pointerCount;
6550 uint32_t lastPointerCount = last->rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006551
Michael Wright842500e2015-03-13 17:32:02 -07006552 current->rawPointerData.clearIdBits();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006553
6554 if (currentPointerCount == 0) {
6555 // No pointers to assign.
6556 return;
6557 }
6558
6559 if (lastPointerCount == 0) {
6560 // All pointers are new.
6561 for (uint32_t i = 0; i < currentPointerCount; i++) {
6562 uint32_t id = i;
Michael Wright842500e2015-03-13 17:32:02 -07006563 current->rawPointerData.pointers[i].id = id;
6564 current->rawPointerData.idToIndex[id] = i;
6565 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006566 }
6567 return;
6568 }
6569
6570 if (currentPointerCount == 1 && lastPointerCount == 1
Michael Wright842500e2015-03-13 17:32:02 -07006571 && current->rawPointerData.pointers[0].toolType
6572 == last->rawPointerData.pointers[0].toolType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006573 // Only one pointer and no change in count so it must have the same id as before.
Michael Wright842500e2015-03-13 17:32:02 -07006574 uint32_t id = last->rawPointerData.pointers[0].id;
6575 current->rawPointerData.pointers[0].id = id;
6576 current->rawPointerData.idToIndex[id] = 0;
6577 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006578 return;
6579 }
6580
6581 // General case.
6582 // We build a heap of squared euclidean distances between current and last pointers
6583 // associated with the current and last pointer indices. Then, we find the best
6584 // match (by distance) for each current pointer.
6585 // The pointers must have the same tool type but it is possible for them to
6586 // transition from hovering to touching or vice-versa while retaining the same id.
6587 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
6588
6589 uint32_t heapSize = 0;
6590 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
6591 currentPointerIndex++) {
6592 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
6593 lastPointerIndex++) {
6594 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006595 current->rawPointerData.pointers[currentPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006596 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006597 last->rawPointerData.pointers[lastPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006598 if (currentPointer.toolType == lastPointer.toolType) {
6599 int64_t deltaX = currentPointer.x - lastPointer.x;
6600 int64_t deltaY = currentPointer.y - lastPointer.y;
6601
6602 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
6603
6604 // Insert new element into the heap (sift up).
6605 heap[heapSize].currentPointerIndex = currentPointerIndex;
6606 heap[heapSize].lastPointerIndex = lastPointerIndex;
6607 heap[heapSize].distance = distance;
6608 heapSize += 1;
6609 }
6610 }
6611 }
6612
6613 // Heapify
6614 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
6615 startIndex -= 1;
6616 for (uint32_t parentIndex = startIndex; ;) {
6617 uint32_t childIndex = parentIndex * 2 + 1;
6618 if (childIndex >= heapSize) {
6619 break;
6620 }
6621
6622 if (childIndex + 1 < heapSize
6623 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6624 childIndex += 1;
6625 }
6626
6627 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6628 break;
6629 }
6630
6631 swap(heap[parentIndex], heap[childIndex]);
6632 parentIndex = childIndex;
6633 }
6634 }
6635
6636#if DEBUG_POINTER_ASSIGNMENT
6637 ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
6638 for (size_t i = 0; i < heapSize; i++) {
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006639 ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006640 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6641 heap[i].distance);
6642 }
6643#endif
6644
6645 // Pull matches out by increasing order of distance.
6646 // To avoid reassigning pointers that have already been matched, the loop keeps track
6647 // of which last and current pointers have been matched using the matchedXXXBits variables.
6648 // It also tracks the used pointer id bits.
6649 BitSet32 matchedLastBits(0);
6650 BitSet32 matchedCurrentBits(0);
6651 BitSet32 usedIdBits(0);
6652 bool first = true;
6653 for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
6654 while (heapSize > 0) {
6655 if (first) {
6656 // The first time through the loop, we just consume the root element of
6657 // the heap (the one with smallest distance).
6658 first = false;
6659 } else {
6660 // Previous iterations consumed the root element of the heap.
6661 // Pop root element off of the heap (sift down).
6662 heap[0] = heap[heapSize];
6663 for (uint32_t parentIndex = 0; ;) {
6664 uint32_t childIndex = parentIndex * 2 + 1;
6665 if (childIndex >= heapSize) {
6666 break;
6667 }
6668
6669 if (childIndex + 1 < heapSize
6670 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6671 childIndex += 1;
6672 }
6673
6674 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6675 break;
6676 }
6677
6678 swap(heap[parentIndex], heap[childIndex]);
6679 parentIndex = childIndex;
6680 }
6681
6682#if DEBUG_POINTER_ASSIGNMENT
6683 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
6684 for (size_t i = 0; i < heapSize; i++) {
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006685 ALOGD(" heap[%zu]: cur=%" PRIu32 ", last=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006686 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6687 heap[i].distance);
6688 }
6689#endif
6690 }
6691
6692 heapSize -= 1;
6693
6694 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
6695 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
6696
6697 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
6698 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
6699
6700 matchedCurrentBits.markBit(currentPointerIndex);
6701 matchedLastBits.markBit(lastPointerIndex);
6702
Michael Wright842500e2015-03-13 17:32:02 -07006703 uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
6704 current->rawPointerData.pointers[currentPointerIndex].id = id;
6705 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6706 current->rawPointerData.markIdBit(id,
6707 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006708 usedIdBits.markBit(id);
6709
6710#if DEBUG_POINTER_ASSIGNMENT
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006711 ALOGD("assignPointerIds - matched: cur=%" PRIu32 ", last=%" PRIu32
6712 ", id=%" PRIu32 ", distance=%" PRIu64,
Michael Wrightd02c5b62014-02-10 15:10:22 -08006713 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
6714#endif
6715 break;
6716 }
6717 }
6718
6719 // Assign fresh ids to pointers that were not matched in the process.
6720 for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
6721 uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
6722 uint32_t id = usedIdBits.markFirstUnmarkedBit();
6723
Michael Wright842500e2015-03-13 17:32:02 -07006724 current->rawPointerData.pointers[currentPointerIndex].id = id;
6725 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6726 current->rawPointerData.markIdBit(id,
6727 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006728
6729#if DEBUG_POINTER_ASSIGNMENT
Siarhei Vishniakou73215292017-10-13 11:02:44 -07006730 ALOGD("assignPointerIds - assigned: cur=%" PRIu32 ", id=%" PRIu32, currentPointerIndex, id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006731#endif
6732 }
6733}
6734
6735int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
6736 if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
6737 return AKEY_STATE_VIRTUAL;
6738 }
6739
6740 size_t numVirtualKeys = mVirtualKeys.size();
6741 for (size_t i = 0; i < numVirtualKeys; i++) {
6742 const VirtualKey& virtualKey = mVirtualKeys[i];
6743 if (virtualKey.keyCode == keyCode) {
6744 return AKEY_STATE_UP;
6745 }
6746 }
6747
6748 return AKEY_STATE_UNKNOWN;
6749}
6750
6751int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
6752 if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
6753 return AKEY_STATE_VIRTUAL;
6754 }
6755
6756 size_t numVirtualKeys = mVirtualKeys.size();
6757 for (size_t i = 0; i < numVirtualKeys; i++) {
6758 const VirtualKey& virtualKey = mVirtualKeys[i];
6759 if (virtualKey.scanCode == scanCode) {
6760 return AKEY_STATE_UP;
6761 }
6762 }
6763
6764 return AKEY_STATE_UNKNOWN;
6765}
6766
6767bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
6768 const int32_t* keyCodes, uint8_t* outFlags) {
6769 size_t numVirtualKeys = mVirtualKeys.size();
6770 for (size_t i = 0; i < numVirtualKeys; i++) {
6771 const VirtualKey& virtualKey = mVirtualKeys[i];
6772
6773 for (size_t i = 0; i < numCodes; i++) {
6774 if (virtualKey.keyCode == keyCodes[i]) {
6775 outFlags[i] = 1;
6776 }
6777 }
6778 }
6779
6780 return true;
6781}
6782
6783
6784// --- SingleTouchInputMapper ---
6785
6786SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
6787 TouchInputMapper(device) {
6788}
6789
6790SingleTouchInputMapper::~SingleTouchInputMapper() {
6791}
6792
6793void SingleTouchInputMapper::reset(nsecs_t when) {
6794 mSingleTouchMotionAccumulator.reset(getDevice());
6795
6796 TouchInputMapper::reset(when);
6797}
6798
6799void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
6800 TouchInputMapper::process(rawEvent);
6801
6802 mSingleTouchMotionAccumulator.process(rawEvent);
6803}
6804
Michael Wright842500e2015-03-13 17:32:02 -07006805void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006806 if (mTouchButtonAccumulator.isToolActive()) {
Michael Wright842500e2015-03-13 17:32:02 -07006807 outState->rawPointerData.pointerCount = 1;
6808 outState->rawPointerData.idToIndex[0] = 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006809
6810 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6811 && (mTouchButtonAccumulator.isHovering()
6812 || (mRawPointerAxes.pressure.valid
6813 && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
Michael Wright842500e2015-03-13 17:32:02 -07006814 outState->rawPointerData.markIdBit(0, isHovering);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006815
Michael Wright842500e2015-03-13 17:32:02 -07006816 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006817 outPointer.id = 0;
6818 outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
6819 outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
6820 outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
6821 outPointer.touchMajor = 0;
6822 outPointer.touchMinor = 0;
6823 outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6824 outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6825 outPointer.orientation = 0;
6826 outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
6827 outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
6828 outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
6829 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6830 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6831 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6832 }
6833 outPointer.isHovering = isHovering;
6834 }
6835}
6836
6837void SingleTouchInputMapper::configureRawPointerAxes() {
6838 TouchInputMapper::configureRawPointerAxes();
6839
6840 getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
6841 getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
6842 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
6843 getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
6844 getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
6845 getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
6846 getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
6847}
6848
6849bool SingleTouchInputMapper::hasStylus() const {
6850 return mTouchButtonAccumulator.hasStylus();
6851}
6852
6853
6854// --- MultiTouchInputMapper ---
6855
6856MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
6857 TouchInputMapper(device) {
6858}
6859
6860MultiTouchInputMapper::~MultiTouchInputMapper() {
6861}
6862
6863void MultiTouchInputMapper::reset(nsecs_t when) {
6864 mMultiTouchMotionAccumulator.reset(getDevice());
6865
6866 mPointerIdBits.clear();
6867
6868 TouchInputMapper::reset(when);
6869}
6870
6871void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
6872 TouchInputMapper::process(rawEvent);
6873
6874 mMultiTouchMotionAccumulator.process(rawEvent);
6875}
6876
Michael Wright842500e2015-03-13 17:32:02 -07006877void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006878 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
6879 size_t outCount = 0;
6880 BitSet32 newPointerIdBits;
gaoshang1a632de2016-08-24 10:23:50 +08006881 mHavePointerIds = true;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006882
6883 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
6884 const MultiTouchMotionAccumulator::Slot* inSlot =
6885 mMultiTouchMotionAccumulator.getSlot(inIndex);
6886 if (!inSlot->isInUse()) {
6887 continue;
6888 }
6889
6890 if (outCount >= MAX_POINTERS) {
6891#if DEBUG_POINTERS
6892 ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
6893 "ignoring the rest.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01006894 getDeviceName().c_str(), MAX_POINTERS);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006895#endif
6896 break; // too many fingers!
6897 }
6898
Michael Wright842500e2015-03-13 17:32:02 -07006899 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006900 outPointer.x = inSlot->getX();
6901 outPointer.y = inSlot->getY();
6902 outPointer.pressure = inSlot->getPressure();
6903 outPointer.touchMajor = inSlot->getTouchMajor();
6904 outPointer.touchMinor = inSlot->getTouchMinor();
6905 outPointer.toolMajor = inSlot->getToolMajor();
6906 outPointer.toolMinor = inSlot->getToolMinor();
6907 outPointer.orientation = inSlot->getOrientation();
6908 outPointer.distance = inSlot->getDistance();
6909 outPointer.tiltX = 0;
6910 outPointer.tiltY = 0;
6911
6912 outPointer.toolType = inSlot->getToolType();
6913 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6914 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6915 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6916 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6917 }
6918 }
6919
6920 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6921 && (mTouchButtonAccumulator.isHovering()
6922 || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
6923 outPointer.isHovering = isHovering;
6924
6925 // Assign pointer id using tracking id if available.
gaoshang1a632de2016-08-24 10:23:50 +08006926 if (mHavePointerIds) {
6927 int32_t trackingId = inSlot->getTrackingId();
6928 int32_t id = -1;
6929 if (trackingId >= 0) {
6930 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
6931 uint32_t n = idBits.clearFirstMarkedBit();
6932 if (mPointerTrackingIdMap[n] == trackingId) {
6933 id = n;
6934 }
6935 }
6936
6937 if (id < 0 && !mPointerIdBits.isFull()) {
6938 id = mPointerIdBits.markFirstUnmarkedBit();
6939 mPointerTrackingIdMap[id] = trackingId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006940 }
Michael Wright842500e2015-03-13 17:32:02 -07006941 }
gaoshang1a632de2016-08-24 10:23:50 +08006942 if (id < 0) {
6943 mHavePointerIds = false;
6944 outState->rawPointerData.clearIdBits();
6945 newPointerIdBits.clear();
6946 } else {
6947 outPointer.id = id;
6948 outState->rawPointerData.idToIndex[id] = outCount;
6949 outState->rawPointerData.markIdBit(id, isHovering);
6950 newPointerIdBits.markBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006951 }
Michael Wright842500e2015-03-13 17:32:02 -07006952 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08006953 outCount += 1;
6954 }
6955
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08006956 outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
Michael Wright842500e2015-03-13 17:32:02 -07006957 outState->rawPointerData.pointerCount = outCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006958 mPointerIdBits = newPointerIdBits;
6959
6960 mMultiTouchMotionAccumulator.finishSync();
6961}
6962
6963void MultiTouchInputMapper::configureRawPointerAxes() {
6964 TouchInputMapper::configureRawPointerAxes();
6965
6966 getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
6967 getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
6968 getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
6969 getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
6970 getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
6971 getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
6972 getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
6973 getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
6974 getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
6975 getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
6976 getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
6977
6978 if (mRawPointerAxes.trackingId.valid
6979 && mRawPointerAxes.slot.valid
6980 && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
6981 size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
6982 if (slotCount > MAX_SLOTS) {
Narayan Kamath37764c72014-03-27 14:21:09 +00006983 ALOGW("MultiTouch Device %s reported %zu slots but the framework "
6984 "only supports a maximum of %zu slots at this time.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01006985 getDeviceName().c_str(), slotCount, MAX_SLOTS);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006986 slotCount = MAX_SLOTS;
6987 }
6988 mMultiTouchMotionAccumulator.configure(getDevice(),
6989 slotCount, true /*usingSlotsProtocol*/);
6990 } else {
6991 mMultiTouchMotionAccumulator.configure(getDevice(),
6992 MAX_POINTERS, false /*usingSlotsProtocol*/);
6993 }
6994}
6995
6996bool MultiTouchInputMapper::hasStylus() const {
6997 return mMultiTouchMotionAccumulator.hasStylus()
6998 || mTouchButtonAccumulator.hasStylus();
6999}
7000
Michael Wright842500e2015-03-13 17:32:02 -07007001// --- ExternalStylusInputMapper
7002
7003ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
7004 InputMapper(device) {
7005
7006}
7007
7008uint32_t ExternalStylusInputMapper::getSources() {
7009 return AINPUT_SOURCE_STYLUS;
7010}
7011
7012void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
7013 InputMapper::populateDeviceInfo(info);
7014 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
7015 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
7016}
7017
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007018void ExternalStylusInputMapper::dump(std::string& dump) {
7019 dump += INDENT2 "External Stylus Input Mapper:\n";
7020 dump += INDENT3 "Raw Stylus Axes:\n";
Michael Wright842500e2015-03-13 17:32:02 -07007021 dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007022 dump += INDENT3 "Stylus State:\n";
Michael Wright842500e2015-03-13 17:32:02 -07007023 dumpStylusState(dump, mStylusState);
7024}
7025
7026void ExternalStylusInputMapper::configure(nsecs_t when,
7027 const InputReaderConfiguration* config, uint32_t changes) {
7028 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
7029 mTouchButtonAccumulator.configure(getDevice());
7030}
7031
7032void ExternalStylusInputMapper::reset(nsecs_t when) {
7033 InputDevice* device = getDevice();
7034 mSingleTouchMotionAccumulator.reset(device);
7035 mTouchButtonAccumulator.reset(device);
7036 InputMapper::reset(when);
7037}
7038
7039void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
7040 mSingleTouchMotionAccumulator.process(rawEvent);
7041 mTouchButtonAccumulator.process(rawEvent);
7042
7043 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
7044 sync(rawEvent->when);
7045 }
7046}
7047
7048void ExternalStylusInputMapper::sync(nsecs_t when) {
7049 mStylusState.clear();
7050
7051 mStylusState.when = when;
7052
Michael Wright45ccacf2015-04-21 19:01:58 +01007053 mStylusState.toolType = mTouchButtonAccumulator.getToolType();
7054 if (mStylusState.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
7055 mStylusState.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
7056 }
7057
Michael Wright842500e2015-03-13 17:32:02 -07007058 int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
7059 if (mRawPressureAxis.valid) {
7060 mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
7061 } else if (mTouchButtonAccumulator.isToolActive()) {
7062 mStylusState.pressure = 1.0f;
7063 } else {
7064 mStylusState.pressure = 0.0f;
7065 }
7066
7067 mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
Michael Wright842500e2015-03-13 17:32:02 -07007068
7069 mContext->dispatchExternalStylusState(mStylusState);
7070}
7071
Michael Wrightd02c5b62014-02-10 15:10:22 -08007072
7073// --- JoystickInputMapper ---
7074
7075JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
7076 InputMapper(device) {
7077}
7078
7079JoystickInputMapper::~JoystickInputMapper() {
7080}
7081
7082uint32_t JoystickInputMapper::getSources() {
7083 return AINPUT_SOURCE_JOYSTICK;
7084}
7085
7086void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
7087 InputMapper::populateDeviceInfo(info);
7088
7089 for (size_t i = 0; i < mAxes.size(); i++) {
7090 const Axis& axis = mAxes.valueAt(i);
7091 addMotionRange(axis.axisInfo.axis, axis, info);
7092
7093 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7094 addMotionRange(axis.axisInfo.highAxis, axis, info);
7095
7096 }
7097 }
7098}
7099
7100void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
7101 InputDeviceInfo* info) {
7102 info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
7103 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
7104 /* In order to ease the transition for developers from using the old axes
7105 * to the newer, more semantically correct axes, we'll continue to register
7106 * the old axes as duplicates of their corresponding new ones. */
7107 int32_t compatAxis = getCompatAxis(axisId);
7108 if (compatAxis >= 0) {
7109 info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
7110 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
7111 }
7112}
7113
7114/* A mapping from axes the joystick actually has to the axes that should be
7115 * artificially created for compatibility purposes.
7116 * Returns -1 if no compatibility axis is needed. */
7117int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
7118 switch(axis) {
7119 case AMOTION_EVENT_AXIS_LTRIGGER:
7120 return AMOTION_EVENT_AXIS_BRAKE;
7121 case AMOTION_EVENT_AXIS_RTRIGGER:
7122 return AMOTION_EVENT_AXIS_GAS;
7123 }
7124 return -1;
7125}
7126
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007127void JoystickInputMapper::dump(std::string& dump) {
7128 dump += INDENT2 "Joystick Input Mapper:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007129
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007130 dump += INDENT3 "Axes:\n";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007131 size_t numAxes = mAxes.size();
7132 for (size_t i = 0; i < numAxes; i++) {
7133 const Axis& axis = mAxes.valueAt(i);
7134 const char* label = getAxisLabel(axis.axisInfo.axis);
7135 if (label) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007136 dump += StringPrintf(INDENT4 "%s", label);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007137 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007138 dump += StringPrintf(INDENT4 "%d", axis.axisInfo.axis);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007139 }
7140 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7141 label = getAxisLabel(axis.axisInfo.highAxis);
7142 if (label) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007143 dump += StringPrintf(" / %s (split at %d)", label, axis.axisInfo.splitValue);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007144 } else {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007145 dump += StringPrintf(" / %d (split at %d)", axis.axisInfo.highAxis,
Michael Wrightd02c5b62014-02-10 15:10:22 -08007146 axis.axisInfo.splitValue);
7147 }
7148 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007149 dump += " (invert)";
Michael Wrightd02c5b62014-02-10 15:10:22 -08007150 }
7151
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007152 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 -08007153 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007154 dump += StringPrintf(INDENT4 " scale=%0.5f, offset=%0.5f, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08007155 "highScale=%0.5f, highOffset=%0.5f\n",
7156 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Siarhei Vishniakouf93fcf42017-11-22 16:00:14 -08007157 dump += StringPrintf(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08007158 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
7159 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
7160 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
7161 }
7162}
7163
7164void JoystickInputMapper::configure(nsecs_t when,
7165 const InputReaderConfiguration* config, uint32_t changes) {
7166 InputMapper::configure(when, config, changes);
7167
7168 if (!changes) { // first time only
7169 // Collect all axes.
7170 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
7171 if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
7172 & INPUT_DEVICE_CLASS_JOYSTICK)) {
7173 continue; // axis must be claimed by a different device
7174 }
7175
7176 RawAbsoluteAxisInfo rawAxisInfo;
7177 getAbsoluteAxisInfo(abs, &rawAxisInfo);
7178 if (rawAxisInfo.valid) {
7179 // Map axis.
7180 AxisInfo axisInfo;
7181 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
7182 if (!explicitlyMapped) {
7183 // Axis is not explicitly mapped, will choose a generic axis later.
7184 axisInfo.mode = AxisInfo::MODE_NORMAL;
7185 axisInfo.axis = -1;
7186 }
7187
7188 // Apply flat override.
7189 int32_t rawFlat = axisInfo.flatOverride < 0
7190 ? rawAxisInfo.flat : axisInfo.flatOverride;
7191
7192 // Calculate scaling factors and limits.
7193 Axis axis;
7194 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
7195 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
7196 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
7197 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7198 scale, 0.0f, highScale, 0.0f,
7199 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7200 rawAxisInfo.resolution * scale);
7201 } else if (isCenteredAxis(axisInfo.axis)) {
7202 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
7203 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
7204 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7205 scale, offset, scale, offset,
7206 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7207 rawAxisInfo.resolution * scale);
7208 } else {
7209 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
7210 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
7211 scale, 0.0f, scale, 0.0f,
7212 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
7213 rawAxisInfo.resolution * scale);
7214 }
7215
7216 // To eliminate noise while the joystick is at rest, filter out small variations
7217 // in axis values up front.
7218 axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
7219
7220 mAxes.add(abs, axis);
7221 }
7222 }
7223
7224 // If there are too many axes, start dropping them.
7225 // Prefer to keep explicitly mapped axes.
7226 if (mAxes.size() > PointerCoords::MAX_AXES) {
Narayan Kamath37764c72014-03-27 14:21:09 +00007227 ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007228 getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007229 pruneAxes(true);
7230 pruneAxes(false);
7231 }
7232
7233 // Assign generic axis ids to remaining axes.
7234 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
7235 size_t numAxes = mAxes.size();
7236 for (size_t i = 0; i < numAxes; i++) {
7237 Axis& axis = mAxes.editValueAt(i);
7238 if (axis.axisInfo.axis < 0) {
7239 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
7240 && haveAxis(nextGenericAxisId)) {
7241 nextGenericAxisId += 1;
7242 }
7243
7244 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
7245 axis.axisInfo.axis = nextGenericAxisId;
7246 nextGenericAxisId += 1;
7247 } else {
7248 ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
7249 "have already been assigned to other axes.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007250 getDeviceName().c_str(), mAxes.keyAt(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08007251 mAxes.removeItemsAt(i--);
7252 numAxes -= 1;
7253 }
7254 }
7255 }
7256 }
7257}
7258
7259bool JoystickInputMapper::haveAxis(int32_t axisId) {
7260 size_t numAxes = mAxes.size();
7261 for (size_t i = 0; i < numAxes; i++) {
7262 const Axis& axis = mAxes.valueAt(i);
7263 if (axis.axisInfo.axis == axisId
7264 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
7265 && axis.axisInfo.highAxis == axisId)) {
7266 return true;
7267 }
7268 }
7269 return false;
7270}
7271
7272void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
7273 size_t i = mAxes.size();
7274 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
7275 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
7276 continue;
7277 }
7278 ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01007279 getDeviceName().c_str(), mAxes.keyAt(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08007280 mAxes.removeItemsAt(i);
7281 }
7282}
7283
7284bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
7285 switch (axis) {
7286 case AMOTION_EVENT_AXIS_X:
7287 case AMOTION_EVENT_AXIS_Y:
7288 case AMOTION_EVENT_AXIS_Z:
7289 case AMOTION_EVENT_AXIS_RX:
7290 case AMOTION_EVENT_AXIS_RY:
7291 case AMOTION_EVENT_AXIS_RZ:
7292 case AMOTION_EVENT_AXIS_HAT_X:
7293 case AMOTION_EVENT_AXIS_HAT_Y:
7294 case AMOTION_EVENT_AXIS_ORIENTATION:
7295 case AMOTION_EVENT_AXIS_RUDDER:
7296 case AMOTION_EVENT_AXIS_WHEEL:
7297 return true;
7298 default:
7299 return false;
7300 }
7301}
7302
7303void JoystickInputMapper::reset(nsecs_t when) {
7304 // Recenter all axes.
7305 size_t numAxes = mAxes.size();
7306 for (size_t i = 0; i < numAxes; i++) {
7307 Axis& axis = mAxes.editValueAt(i);
7308 axis.resetValue();
7309 }
7310
7311 InputMapper::reset(when);
7312}
7313
7314void JoystickInputMapper::process(const RawEvent* rawEvent) {
7315 switch (rawEvent->type) {
7316 case EV_ABS: {
7317 ssize_t index = mAxes.indexOfKey(rawEvent->code);
7318 if (index >= 0) {
7319 Axis& axis = mAxes.editValueAt(index);
7320 float newValue, highNewValue;
7321 switch (axis.axisInfo.mode) {
7322 case AxisInfo::MODE_INVERT:
7323 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
7324 * axis.scale + axis.offset;
7325 highNewValue = 0.0f;
7326 break;
7327 case AxisInfo::MODE_SPLIT:
7328 if (rawEvent->value < axis.axisInfo.splitValue) {
7329 newValue = (axis.axisInfo.splitValue - rawEvent->value)
7330 * axis.scale + axis.offset;
7331 highNewValue = 0.0f;
7332 } else if (rawEvent->value > axis.axisInfo.splitValue) {
7333 newValue = 0.0f;
7334 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
7335 * axis.highScale + axis.highOffset;
7336 } else {
7337 newValue = 0.0f;
7338 highNewValue = 0.0f;
7339 }
7340 break;
7341 default:
7342 newValue = rawEvent->value * axis.scale + axis.offset;
7343 highNewValue = 0.0f;
7344 break;
7345 }
7346 axis.newValue = newValue;
7347 axis.highNewValue = highNewValue;
7348 }
7349 break;
7350 }
7351
7352 case EV_SYN:
7353 switch (rawEvent->code) {
7354 case SYN_REPORT:
7355 sync(rawEvent->when, false /*force*/);
7356 break;
7357 }
7358 break;
7359 }
7360}
7361
7362void JoystickInputMapper::sync(nsecs_t when, bool force) {
7363 if (!filterAxes(force)) {
7364 return;
7365 }
7366
7367 int32_t metaState = mContext->getGlobalMetaState();
7368 int32_t buttonState = 0;
7369
7370 PointerProperties pointerProperties;
7371 pointerProperties.clear();
7372 pointerProperties.id = 0;
7373 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
7374
7375 PointerCoords pointerCoords;
7376 pointerCoords.clear();
7377
7378 size_t numAxes = mAxes.size();
7379 for (size_t i = 0; i < numAxes; i++) {
7380 const Axis& axis = mAxes.valueAt(i);
7381 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
7382 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7383 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
7384 axis.highCurrentValue);
7385 }
7386 }
7387
7388 // Moving a joystick axis should not wake the device because joysticks can
7389 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
7390 // button will likely wake the device.
7391 // TODO: Use the input device configuration to control this behavior more finely.
7392 uint32_t policyFlags = 0;
7393
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08007394 NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE,
7395 policyFlags,
Michael Wright7b159c92015-05-14 14:48:03 +01007396 AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
Siarhei Vishniakou777a10b2018-01-31 16:45:06 -08007397 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
Siarhei Vishniakou16f90692017-12-27 14:29:55 -08007398 0, 0, 0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08007399 getListener()->notifyMotion(&args);
7400}
7401
7402void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
7403 int32_t axis, float value) {
7404 pointerCoords->setAxisValue(axis, value);
7405 /* In order to ease the transition for developers from using the old axes
7406 * to the newer, more semantically correct axes, we'll continue to produce
7407 * values for the old axes as mirrors of the value of their corresponding
7408 * new axes. */
7409 int32_t compatAxis = getCompatAxis(axis);
7410 if (compatAxis >= 0) {
7411 pointerCoords->setAxisValue(compatAxis, value);
7412 }
7413}
7414
7415bool JoystickInputMapper::filterAxes(bool force) {
7416 bool atLeastOneSignificantChange = force;
7417 size_t numAxes = mAxes.size();
7418 for (size_t i = 0; i < numAxes; i++) {
7419 Axis& axis = mAxes.editValueAt(i);
7420 if (force || hasValueChangedSignificantly(axis.filter,
7421 axis.newValue, axis.currentValue, axis.min, axis.max)) {
7422 axis.currentValue = axis.newValue;
7423 atLeastOneSignificantChange = true;
7424 }
7425 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
7426 if (force || hasValueChangedSignificantly(axis.filter,
7427 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
7428 axis.highCurrentValue = axis.highNewValue;
7429 atLeastOneSignificantChange = true;
7430 }
7431 }
7432 }
7433 return atLeastOneSignificantChange;
7434}
7435
7436bool JoystickInputMapper::hasValueChangedSignificantly(
7437 float filter, float newValue, float currentValue, float min, float max) {
7438 if (newValue != currentValue) {
7439 // Filter out small changes in value unless the value is converging on the axis
7440 // bounds or center point. This is intended to reduce the amount of information
7441 // sent to applications by particularly noisy joysticks (such as PS3).
7442 if (fabs(newValue - currentValue) > filter
7443 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
7444 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
7445 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
7446 return true;
7447 }
7448 }
7449 return false;
7450}
7451
7452bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
7453 float filter, float newValue, float currentValue, float thresholdValue) {
7454 float newDistance = fabs(newValue - thresholdValue);
7455 if (newDistance < filter) {
7456 float oldDistance = fabs(currentValue - thresholdValue);
7457 if (newDistance < oldDistance) {
7458 return true;
7459 }
7460 }
7461 return false;
7462}
7463
7464} // namespace android