blob: c7d9503b337565eb5d078a304ea15c419b252fe9 [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
47#include <cutils/log.h>
48#include <input/Keyboard.h>
49#include <input/VirtualKeyMap.h>
50
Michael Wright842500e2015-03-13 17:32:02 -070051#include <inttypes.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080052#include <stddef.h>
53#include <stdlib.h>
54#include <unistd.h>
55#include <errno.h>
56#include <limits.h>
57#include <math.h>
58
59#define INDENT " "
60#define INDENT2 " "
61#define INDENT3 " "
62#define INDENT4 " "
63#define INDENT5 " "
64
65namespace android {
66
67// --- Constants ---
68
69// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
70static const size_t MAX_SLOTS = 32;
71
Michael Wright842500e2015-03-13 17:32:02 -070072// Maximum amount of latency to add to touch events while waiting for data from an
73// external stylus.
Michael Wright5e17a5d2015-04-21 22:45:13 +010074static const nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72);
Michael Wright842500e2015-03-13 17:32:02 -070075
Michael Wrightd02c5b62014-02-10 15:10:22 -080076// --- Static Functions ---
77
78template<typename T>
79inline static T abs(const T& value) {
80 return value < 0 ? - value : value;
81}
82
83template<typename T>
84inline static T min(const T& a, const T& b) {
85 return a < b ? a : b;
86}
87
88template<typename T>
89inline static void swap(T& a, T& b) {
90 T temp = a;
91 a = b;
92 b = temp;
93}
94
95inline static float avg(float x, float y) {
96 return (x + y) / 2;
97}
98
99inline static float distance(float x1, float y1, float x2, float y2) {
100 return hypotf(x1 - x2, y1 - y2);
101}
102
103inline static int32_t signExtendNybble(int32_t value) {
104 return value >= 8 ? value - 16 : value;
105}
106
107static inline const char* toString(bool value) {
108 return value ? "true" : "false";
109}
110
111static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
112 const int32_t map[][4], size_t mapSize) {
113 if (orientation != DISPLAY_ORIENTATION_0) {
114 for (size_t i = 0; i < mapSize; i++) {
115 if (value == map[i][0]) {
116 return map[i][orientation];
117 }
118 }
119 }
120 return value;
121}
122
123static const int32_t keyCodeRotationMap[][4] = {
124 // key codes enumerated counter-clockwise with the original (unrotated) key first
125 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
126 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
127 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
128 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
129 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
130};
131static const size_t keyCodeRotationMapSize =
132 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
133
134static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
135 return rotateValueUsingRotationMap(keyCode, orientation,
136 keyCodeRotationMap, keyCodeRotationMapSize);
137}
138
139static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
140 float temp;
141 switch (orientation) {
142 case DISPLAY_ORIENTATION_90:
143 temp = *deltaX;
144 *deltaX = *deltaY;
145 *deltaY = -temp;
146 break;
147
148 case DISPLAY_ORIENTATION_180:
149 *deltaX = -*deltaX;
150 *deltaY = -*deltaY;
151 break;
152
153 case DISPLAY_ORIENTATION_270:
154 temp = *deltaX;
155 *deltaX = -*deltaY;
156 *deltaY = temp;
157 break;
158 }
159}
160
161static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
162 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
163}
164
165// Returns true if the pointer should be reported as being down given the specified
166// button states. This determines whether the event is reported as a touch event.
167static bool isPointerDown(int32_t buttonState) {
168 return buttonState &
169 (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
170 | AMOTION_EVENT_BUTTON_TERTIARY);
171}
172
173static float calculateCommonVector(float a, float b) {
174 if (a > 0 && b > 0) {
175 return a < b ? a : b;
176 } else if (a < 0 && b < 0) {
177 return a > b ? a : b;
178 } else {
179 return 0;
180 }
181}
182
183static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
184 nsecs_t when, int32_t deviceId, uint32_t source,
185 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
186 int32_t buttonState, int32_t keyCode) {
187 if (
188 (action == AKEY_EVENT_ACTION_DOWN
189 && !(lastButtonState & buttonState)
190 && (currentButtonState & buttonState))
191 || (action == AKEY_EVENT_ACTION_UP
192 && (lastButtonState & buttonState)
193 && !(currentButtonState & buttonState))) {
194 NotifyKeyArgs args(when, deviceId, source, policyFlags,
195 action, 0, keyCode, 0, context->getGlobalMetaState(), when);
196 context->getListener()->notifyKey(&args);
197 }
198}
199
200static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
201 nsecs_t when, int32_t deviceId, uint32_t source,
202 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
203 synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
204 lastButtonState, currentButtonState,
205 AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
206 synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
207 lastButtonState, currentButtonState,
208 AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
209}
210
211
212// --- InputReaderConfiguration ---
213
214bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
215 const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
216 if (viewport.displayId >= 0) {
217 *outViewport = viewport;
218 return true;
219 }
220 return false;
221}
222
223void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
224 DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
225 v = viewport;
226}
227
228
Jason Gereckeaf126fb2012-05-10 14:22:47 -0700229// -- TouchAffineTransformation --
230void TouchAffineTransformation::applyTo(float& x, float& y) const {
231 float newX, newY;
232 newX = x * x_scale + y * x_ymix + x_offset;
233 newY = x * y_xmix + y * y_scale + y_offset;
234
235 x = newX;
236 y = newY;
237}
238
239
Michael Wrightd02c5b62014-02-10 15:10:22 -0800240// --- InputReader ---
241
242InputReader::InputReader(const sp<EventHubInterface>& eventHub,
243 const sp<InputReaderPolicyInterface>& policy,
244 const sp<InputListenerInterface>& listener) :
245 mContext(this), mEventHub(eventHub), mPolicy(policy),
246 mGlobalMetaState(0), mGeneration(1),
247 mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
248 mConfigurationChangesToRefresh(0) {
249 mQueuedListener = new QueuedInputListener(listener);
250
251 { // acquire lock
252 AutoMutex _l(mLock);
253
254 refreshConfigurationLocked(0);
255 updateGlobalMetaStateLocked();
256 } // release lock
257}
258
259InputReader::~InputReader() {
260 for (size_t i = 0; i < mDevices.size(); i++) {
261 delete mDevices.valueAt(i);
262 }
263}
264
265void InputReader::loopOnce() {
266 int32_t oldGeneration;
267 int32_t timeoutMillis;
268 bool inputDevicesChanged = false;
269 Vector<InputDeviceInfo> inputDevices;
270 { // acquire lock
271 AutoMutex _l(mLock);
272
273 oldGeneration = mGeneration;
274 timeoutMillis = -1;
275
276 uint32_t changes = mConfigurationChangesToRefresh;
277 if (changes) {
278 mConfigurationChangesToRefresh = 0;
279 timeoutMillis = 0;
280 refreshConfigurationLocked(changes);
281 } else if (mNextTimeout != LLONG_MAX) {
282 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
283 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
284 }
285 } // release lock
286
287 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
288
289 { // acquire lock
290 AutoMutex _l(mLock);
291 mReaderIsAliveCondition.broadcast();
292
293 if (count) {
294 processEventsLocked(mEventBuffer, count);
295 }
296
297 if (mNextTimeout != LLONG_MAX) {
298 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
299 if (now >= mNextTimeout) {
300#if DEBUG_RAW_EVENTS
301 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
302#endif
303 mNextTimeout = LLONG_MAX;
304 timeoutExpiredLocked(now);
305 }
306 }
307
308 if (oldGeneration != mGeneration) {
309 inputDevicesChanged = true;
310 getInputDevicesLocked(inputDevices);
311 }
312 } // release lock
313
314 // Send out a message that the describes the changed input devices.
315 if (inputDevicesChanged) {
316 mPolicy->notifyInputDevicesChanged(inputDevices);
317 }
318
319 // Flush queued events out to the listener.
320 // This must happen outside of the lock because the listener could potentially call
321 // back into the InputReader's methods, such as getScanCodeState, or become blocked
322 // on another thread similarly waiting to acquire the InputReader lock thereby
323 // resulting in a deadlock. This situation is actually quite plausible because the
324 // listener is actually the input dispatcher, which calls into the window manager,
325 // which occasionally calls into the input reader.
326 mQueuedListener->flush();
327}
328
329void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
330 for (const RawEvent* rawEvent = rawEvents; count;) {
331 int32_t type = rawEvent->type;
332 size_t batchSize = 1;
333 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
334 int32_t deviceId = rawEvent->deviceId;
335 while (batchSize < count) {
336 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
337 || rawEvent[batchSize].deviceId != deviceId) {
338 break;
339 }
340 batchSize += 1;
341 }
342#if DEBUG_RAW_EVENTS
343 ALOGD("BatchSize: %d Count: %d", batchSize, count);
344#endif
345 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
346 } else {
347 switch (rawEvent->type) {
348 case EventHubInterface::DEVICE_ADDED:
349 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
350 break;
351 case EventHubInterface::DEVICE_REMOVED:
352 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
353 break;
354 case EventHubInterface::FINISHED_DEVICE_SCAN:
355 handleConfigurationChangedLocked(rawEvent->when);
356 break;
357 default:
358 ALOG_ASSERT(false); // can't happen
359 break;
360 }
361 }
362 count -= batchSize;
363 rawEvent += batchSize;
364 }
365}
366
367void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
368 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
369 if (deviceIndex >= 0) {
370 ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
371 return;
372 }
373
374 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
375 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
376 int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
377
378 InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
379 device->configure(when, &mConfig, 0);
380 device->reset(when);
381
382 if (device->isIgnored()) {
383 ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
384 identifier.name.string());
385 } else {
386 ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
387 identifier.name.string(), device->getSources());
388 }
389
390 mDevices.add(deviceId, device);
391 bumpGenerationLocked();
Michael Wright842500e2015-03-13 17:32:02 -0700392
393 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
394 notifyExternalStylusPresenceChanged();
395 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800396}
397
398void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
399 InputDevice* device = NULL;
400 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
401 if (deviceIndex < 0) {
402 ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
403 return;
404 }
405
406 device = mDevices.valueAt(deviceIndex);
407 mDevices.removeItemsAt(deviceIndex, 1);
408 bumpGenerationLocked();
409
410 if (device->isIgnored()) {
411 ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
412 device->getId(), device->getName().string());
413 } else {
414 ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
415 device->getId(), device->getName().string(), device->getSources());
416 }
417
Michael Wright842500e2015-03-13 17:32:02 -0700418 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
419 notifyExternalStylusPresenceChanged();
420 }
421
Michael Wrightd02c5b62014-02-10 15:10:22 -0800422 device->reset(when);
423 delete device;
424}
425
426InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
427 const InputDeviceIdentifier& identifier, uint32_t classes) {
428 InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
429 controllerNumber, identifier, classes);
430
431 // External devices.
432 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
433 device->setExternal(true);
434 }
435
Tim Kilbourn063ff532015-04-08 10:26:18 -0700436 // Devices with mics.
437 if (classes & INPUT_DEVICE_CLASS_MIC) {
438 device->setMic(true);
439 }
440
Michael Wrightd02c5b62014-02-10 15:10:22 -0800441 // Switch-like devices.
442 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
443 device->addMapper(new SwitchInputMapper(device));
444 }
445
446 // Vibrator-like devices.
447 if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
448 device->addMapper(new VibratorInputMapper(device));
449 }
450
451 // Keyboard-like devices.
452 uint32_t keyboardSource = 0;
453 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
454 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
455 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
456 }
457 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
458 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
459 }
460 if (classes & INPUT_DEVICE_CLASS_DPAD) {
461 keyboardSource |= AINPUT_SOURCE_DPAD;
462 }
463 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
464 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
465 }
466
467 if (keyboardSource != 0) {
468 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
469 }
470
471 // Cursor-like devices.
472 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
473 device->addMapper(new CursorInputMapper(device));
474 }
475
476 // Touchscreens and touchpad devices.
477 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
478 device->addMapper(new MultiTouchInputMapper(device));
479 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
480 device->addMapper(new SingleTouchInputMapper(device));
481 }
482
483 // Joystick-like devices.
484 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
485 device->addMapper(new JoystickInputMapper(device));
486 }
487
Michael Wright842500e2015-03-13 17:32:02 -0700488 // External stylus-like devices.
489 if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
490 device->addMapper(new ExternalStylusInputMapper(device));
491 }
492
Michael Wrightd02c5b62014-02-10 15:10:22 -0800493 return device;
494}
495
496void InputReader::processEventsForDeviceLocked(int32_t deviceId,
497 const RawEvent* rawEvents, size_t count) {
498 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
499 if (deviceIndex < 0) {
500 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
501 return;
502 }
503
504 InputDevice* device = mDevices.valueAt(deviceIndex);
505 if (device->isIgnored()) {
506 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
507 return;
508 }
509
510 device->process(rawEvents, count);
511}
512
513void InputReader::timeoutExpiredLocked(nsecs_t when) {
514 for (size_t i = 0; i < mDevices.size(); i++) {
515 InputDevice* device = mDevices.valueAt(i);
516 if (!device->isIgnored()) {
517 device->timeoutExpired(when);
518 }
519 }
520}
521
522void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
523 // Reset global meta state because it depends on the list of all configured devices.
524 updateGlobalMetaStateLocked();
525
526 // Enqueue configuration changed.
527 NotifyConfigurationChangedArgs args(when);
528 mQueuedListener->notifyConfigurationChanged(&args);
529}
530
531void InputReader::refreshConfigurationLocked(uint32_t changes) {
532 mPolicy->getReaderConfiguration(&mConfig);
533 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
534
535 if (changes) {
536 ALOGI("Reconfiguring input devices. changes=0x%08x", changes);
537 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
538
539 if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
540 mEventHub->requestReopenDevices();
541 } else {
542 for (size_t i = 0; i < mDevices.size(); i++) {
543 InputDevice* device = mDevices.valueAt(i);
544 device->configure(now, &mConfig, changes);
545 }
546 }
547 }
548}
549
550void InputReader::updateGlobalMetaStateLocked() {
551 mGlobalMetaState = 0;
552
553 for (size_t i = 0; i < mDevices.size(); i++) {
554 InputDevice* device = mDevices.valueAt(i);
555 mGlobalMetaState |= device->getMetaState();
556 }
557}
558
559int32_t InputReader::getGlobalMetaStateLocked() {
560 return mGlobalMetaState;
561}
562
Michael Wright842500e2015-03-13 17:32:02 -0700563void InputReader::notifyExternalStylusPresenceChanged() {
564 refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
565}
566
567void InputReader::getExternalStylusDevicesLocked(Vector<InputDeviceInfo>& outDevices) {
568 for (size_t i = 0; i < mDevices.size(); i++) {
569 InputDevice* device = mDevices.valueAt(i);
570 if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
571 outDevices.push();
572 device->getDeviceInfo(&outDevices.editTop());
573 }
574 }
575}
576
577void InputReader::dispatchExternalStylusState(const StylusState& state) {
578 for (size_t i = 0; i < mDevices.size(); i++) {
579 InputDevice* device = mDevices.valueAt(i);
580 device->updateExternalStylusState(state);
581 }
582}
583
Michael Wrightd02c5b62014-02-10 15:10:22 -0800584void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
585 mDisableVirtualKeysTimeout = time;
586}
587
588bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
589 InputDevice* device, int32_t keyCode, int32_t scanCode) {
590 if (now < mDisableVirtualKeysTimeout) {
591 ALOGI("Dropping virtual key from device %s because virtual keys are "
592 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
593 device->getName().string(),
594 (mDisableVirtualKeysTimeout - now) * 0.000001,
595 keyCode, scanCode);
596 return true;
597 } else {
598 return false;
599 }
600}
601
602void InputReader::fadePointerLocked() {
603 for (size_t i = 0; i < mDevices.size(); i++) {
604 InputDevice* device = mDevices.valueAt(i);
605 device->fadePointer();
606 }
607}
608
609void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
610 if (when < mNextTimeout) {
611 mNextTimeout = when;
612 mEventHub->wake();
613 }
614}
615
616int32_t InputReader::bumpGenerationLocked() {
617 return ++mGeneration;
618}
619
620void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) {
621 AutoMutex _l(mLock);
622 getInputDevicesLocked(outInputDevices);
623}
624
625void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) {
626 outInputDevices.clear();
627
628 size_t numDevices = mDevices.size();
629 for (size_t i = 0; i < numDevices; i++) {
630 InputDevice* device = mDevices.valueAt(i);
631 if (!device->isIgnored()) {
632 outInputDevices.push();
633 device->getDeviceInfo(&outInputDevices.editTop());
634 }
635 }
636}
637
638int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
639 int32_t keyCode) {
640 AutoMutex _l(mLock);
641
642 return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
643}
644
645int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
646 int32_t scanCode) {
647 AutoMutex _l(mLock);
648
649 return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
650}
651
652int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
653 AutoMutex _l(mLock);
654
655 return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
656}
657
658int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
659 GetStateFunc getStateFunc) {
660 int32_t result = AKEY_STATE_UNKNOWN;
661 if (deviceId >= 0) {
662 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
663 if (deviceIndex >= 0) {
664 InputDevice* device = mDevices.valueAt(deviceIndex);
665 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
666 result = (device->*getStateFunc)(sourceMask, code);
667 }
668 }
669 } else {
670 size_t numDevices = mDevices.size();
671 for (size_t i = 0; i < numDevices; i++) {
672 InputDevice* device = mDevices.valueAt(i);
673 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
674 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
675 // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
676 int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
677 if (currentResult >= AKEY_STATE_DOWN) {
678 return currentResult;
679 } else if (currentResult == AKEY_STATE_UP) {
680 result = currentResult;
681 }
682 }
683 }
684 }
685 return result;
686}
687
688bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
689 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
690 AutoMutex _l(mLock);
691
692 memset(outFlags, 0, numCodes);
693 return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
694}
695
696bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
697 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
698 bool result = false;
699 if (deviceId >= 0) {
700 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
701 if (deviceIndex >= 0) {
702 InputDevice* device = mDevices.valueAt(deviceIndex);
703 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
704 result = device->markSupportedKeyCodes(sourceMask,
705 numCodes, keyCodes, outFlags);
706 }
707 }
708 } else {
709 size_t numDevices = mDevices.size();
710 for (size_t i = 0; i < numDevices; i++) {
711 InputDevice* device = mDevices.valueAt(i);
712 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
713 result |= device->markSupportedKeyCodes(sourceMask,
714 numCodes, keyCodes, outFlags);
715 }
716 }
717 }
718 return result;
719}
720
721void InputReader::requestRefreshConfiguration(uint32_t changes) {
722 AutoMutex _l(mLock);
723
724 if (changes) {
725 bool needWake = !mConfigurationChangesToRefresh;
726 mConfigurationChangesToRefresh |= changes;
727
728 if (needWake) {
729 mEventHub->wake();
730 }
731 }
732}
733
734void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
735 ssize_t repeat, int32_t token) {
736 AutoMutex _l(mLock);
737
738 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
739 if (deviceIndex >= 0) {
740 InputDevice* device = mDevices.valueAt(deviceIndex);
741 device->vibrate(pattern, patternSize, repeat, token);
742 }
743}
744
745void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
746 AutoMutex _l(mLock);
747
748 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
749 if (deviceIndex >= 0) {
750 InputDevice* device = mDevices.valueAt(deviceIndex);
751 device->cancelVibrate(token);
752 }
753}
754
755void InputReader::dump(String8& dump) {
756 AutoMutex _l(mLock);
757
758 mEventHub->dump(dump);
759 dump.append("\n");
760
761 dump.append("Input Reader State:\n");
762
763 for (size_t i = 0; i < mDevices.size(); i++) {
764 mDevices.valueAt(i)->dump(dump);
765 }
766
767 dump.append(INDENT "Configuration:\n");
768 dump.append(INDENT2 "ExcludedDeviceNames: [");
769 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
770 if (i != 0) {
771 dump.append(", ");
772 }
773 dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
774 }
775 dump.append("]\n");
776 dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
777 mConfig.virtualKeyQuietTime * 0.000001f);
778
779 dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
780 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
781 mConfig.pointerVelocityControlParameters.scale,
782 mConfig.pointerVelocityControlParameters.lowThreshold,
783 mConfig.pointerVelocityControlParameters.highThreshold,
784 mConfig.pointerVelocityControlParameters.acceleration);
785
786 dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
787 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
788 mConfig.wheelVelocityControlParameters.scale,
789 mConfig.wheelVelocityControlParameters.lowThreshold,
790 mConfig.wheelVelocityControlParameters.highThreshold,
791 mConfig.wheelVelocityControlParameters.acceleration);
792
793 dump.appendFormat(INDENT2 "PointerGesture:\n");
794 dump.appendFormat(INDENT3 "Enabled: %s\n",
795 toString(mConfig.pointerGesturesEnabled));
796 dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
797 mConfig.pointerGestureQuietInterval * 0.000001f);
798 dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
799 mConfig.pointerGestureDragMinSwitchSpeed);
800 dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
801 mConfig.pointerGestureTapInterval * 0.000001f);
802 dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
803 mConfig.pointerGestureTapDragInterval * 0.000001f);
804 dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
805 mConfig.pointerGestureTapSlop);
806 dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
807 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
808 dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
809 mConfig.pointerGestureMultitouchMinDistance);
810 dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
811 mConfig.pointerGestureSwipeTransitionAngleCosine);
812 dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
813 mConfig.pointerGestureSwipeMaxWidthRatio);
814 dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
815 mConfig.pointerGestureMovementSpeedRatio);
816 dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
817 mConfig.pointerGestureZoomSpeedRatio);
818}
819
820void InputReader::monitor() {
821 // Acquire and release the lock to ensure that the reader has not deadlocked.
822 mLock.lock();
823 mEventHub->wake();
824 mReaderIsAliveCondition.wait(mLock);
825 mLock.unlock();
826
827 // Check the EventHub
828 mEventHub->monitor();
829}
830
831
832// --- InputReader::ContextImpl ---
833
834InputReader::ContextImpl::ContextImpl(InputReader* reader) :
835 mReader(reader) {
836}
837
838void InputReader::ContextImpl::updateGlobalMetaState() {
839 // lock is already held by the input loop
840 mReader->updateGlobalMetaStateLocked();
841}
842
843int32_t InputReader::ContextImpl::getGlobalMetaState() {
844 // lock is already held by the input loop
845 return mReader->getGlobalMetaStateLocked();
846}
847
848void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
849 // lock is already held by the input loop
850 mReader->disableVirtualKeysUntilLocked(time);
851}
852
853bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
854 InputDevice* device, int32_t keyCode, int32_t scanCode) {
855 // lock is already held by the input loop
856 return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
857}
858
859void InputReader::ContextImpl::fadePointer() {
860 // lock is already held by the input loop
861 mReader->fadePointerLocked();
862}
863
864void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
865 // lock is already held by the input loop
866 mReader->requestTimeoutAtTimeLocked(when);
867}
868
869int32_t InputReader::ContextImpl::bumpGeneration() {
870 // lock is already held by the input loop
871 return mReader->bumpGenerationLocked();
872}
873
Michael Wright842500e2015-03-13 17:32:02 -0700874void InputReader::ContextImpl::getExternalStylusDevices(Vector<InputDeviceInfo>& outDevices) {
875 // lock is already held by whatever called refreshConfigurationLocked
876 mReader->getExternalStylusDevicesLocked(outDevices);
877}
878
879void InputReader::ContextImpl::dispatchExternalStylusState(const StylusState& state) {
880 mReader->dispatchExternalStylusState(state);
881}
882
Michael Wrightd02c5b62014-02-10 15:10:22 -0800883InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
884 return mReader->mPolicy.get();
885}
886
887InputListenerInterface* InputReader::ContextImpl::getListener() {
888 return mReader->mQueuedListener.get();
889}
890
891EventHubInterface* InputReader::ContextImpl::getEventHub() {
892 return mReader->mEventHub.get();
893}
894
895
896// --- InputReaderThread ---
897
898InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
899 Thread(/*canCallJava*/ true), mReader(reader) {
900}
901
902InputReaderThread::~InputReaderThread() {
903}
904
905bool InputReaderThread::threadLoop() {
906 mReader->loopOnce();
907 return true;
908}
909
910
911// --- InputDevice ---
912
913InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
914 int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
915 mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
916 mIdentifier(identifier), mClasses(classes),
Tim Kilbourn063ff532015-04-08 10:26:18 -0700917 mSources(0), mIsExternal(false), mHasMic(false), mDropUntilNextSync(false) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800918}
919
920InputDevice::~InputDevice() {
921 size_t numMappers = mMappers.size();
922 for (size_t i = 0; i < numMappers; i++) {
923 delete mMappers[i];
924 }
925 mMappers.clear();
926}
927
928void InputDevice::dump(String8& dump) {
929 InputDeviceInfo deviceInfo;
930 getDeviceInfo(& deviceInfo);
931
932 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
933 deviceInfo.getDisplayName().string());
934 dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
935 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Tim Kilbourn063ff532015-04-08 10:26:18 -0700936 dump.appendFormat(INDENT2 "HasMic: %s\n", toString(mHasMic));
Michael Wrightd02c5b62014-02-10 15:10:22 -0800937 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
938 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
939
940 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
941 if (!ranges.isEmpty()) {
942 dump.append(INDENT2 "Motion Ranges:\n");
943 for (size_t i = 0; i < ranges.size(); i++) {
944 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
945 const char* label = getAxisLabel(range.axis);
946 char name[32];
947 if (label) {
948 strncpy(name, label, sizeof(name));
949 name[sizeof(name) - 1] = '\0';
950 } else {
951 snprintf(name, sizeof(name), "%d", range.axis);
952 }
953 dump.appendFormat(INDENT3 "%s: source=0x%08x, "
954 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
955 name, range.source, range.min, range.max, range.flat, range.fuzz,
956 range.resolution);
957 }
958 }
959
960 size_t numMappers = mMappers.size();
961 for (size_t i = 0; i < numMappers; i++) {
962 InputMapper* mapper = mMappers[i];
963 mapper->dump(dump);
964 }
965}
966
967void InputDevice::addMapper(InputMapper* mapper) {
968 mMappers.add(mapper);
969}
970
971void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
972 mSources = 0;
973
974 if (!isIgnored()) {
975 if (!changes) { // first time only
976 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
977 }
978
979 if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
980 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
981 sp<KeyCharacterMap> keyboardLayout =
982 mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
983 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
984 bumpGeneration();
985 }
986 }
987 }
988
989 if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
990 if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
991 String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
992 if (mAlias != alias) {
993 mAlias = alias;
994 bumpGeneration();
995 }
996 }
997 }
998
999 size_t numMappers = mMappers.size();
1000 for (size_t i = 0; i < numMappers; i++) {
1001 InputMapper* mapper = mMappers[i];
1002 mapper->configure(when, config, changes);
1003 mSources |= mapper->getSources();
1004 }
1005 }
1006}
1007
1008void InputDevice::reset(nsecs_t when) {
1009 size_t numMappers = mMappers.size();
1010 for (size_t i = 0; i < numMappers; i++) {
1011 InputMapper* mapper = mMappers[i];
1012 mapper->reset(when);
1013 }
1014
1015 mContext->updateGlobalMetaState();
1016
1017 notifyReset(when);
1018}
1019
1020void InputDevice::process(const RawEvent* rawEvents, size_t count) {
1021 // Process all of the events in order for each mapper.
1022 // We cannot simply ask each mapper to process them in bulk because mappers may
1023 // have side-effects that must be interleaved. For example, joystick movement events and
1024 // gamepad button presses are handled by different mappers but they should be dispatched
1025 // in the order received.
1026 size_t numMappers = mMappers.size();
1027 for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
1028#if DEBUG_RAW_EVENTS
1029 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
1030 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
1031 rawEvent->when);
1032#endif
1033
1034 if (mDropUntilNextSync) {
1035 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1036 mDropUntilNextSync = false;
1037#if DEBUG_RAW_EVENTS
1038 ALOGD("Recovered from input event buffer overrun.");
1039#endif
1040 } else {
1041#if DEBUG_RAW_EVENTS
1042 ALOGD("Dropped input event while waiting for next input sync.");
1043#endif
1044 }
1045 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
1046 ALOGI("Detected input event buffer overrun for device %s.", getName().string());
1047 mDropUntilNextSync = true;
1048 reset(rawEvent->when);
1049 } else {
1050 for (size_t i = 0; i < numMappers; i++) {
1051 InputMapper* mapper = mMappers[i];
1052 mapper->process(rawEvent);
1053 }
1054 }
1055 }
1056}
1057
1058void InputDevice::timeoutExpired(nsecs_t when) {
1059 size_t numMappers = mMappers.size();
1060 for (size_t i = 0; i < numMappers; i++) {
1061 InputMapper* mapper = mMappers[i];
1062 mapper->timeoutExpired(when);
1063 }
1064}
1065
Michael Wright842500e2015-03-13 17:32:02 -07001066void InputDevice::updateExternalStylusState(const StylusState& state) {
1067 size_t numMappers = mMappers.size();
1068 for (size_t i = 0; i < numMappers; i++) {
1069 InputMapper* mapper = mMappers[i];
1070 mapper->updateExternalStylusState(state);
1071 }
1072}
1073
Michael Wrightd02c5b62014-02-10 15:10:22 -08001074void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
1075 outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
Tim Kilbourn063ff532015-04-08 10:26:18 -07001076 mIsExternal, mHasMic);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001077 size_t numMappers = mMappers.size();
1078 for (size_t i = 0; i < numMappers; i++) {
1079 InputMapper* mapper = mMappers[i];
1080 mapper->populateDeviceInfo(outDeviceInfo);
1081 }
1082}
1083
1084int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1085 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
1086}
1087
1088int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1089 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
1090}
1091
1092int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1093 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
1094}
1095
1096int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
1097 int32_t result = AKEY_STATE_UNKNOWN;
1098 size_t numMappers = mMappers.size();
1099 for (size_t i = 0; i < numMappers; i++) {
1100 InputMapper* mapper = mMappers[i];
1101 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1102 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
1103 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
1104 int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
1105 if (currentResult >= AKEY_STATE_DOWN) {
1106 return currentResult;
1107 } else if (currentResult == AKEY_STATE_UP) {
1108 result = currentResult;
1109 }
1110 }
1111 }
1112 return result;
1113}
1114
1115bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1116 const int32_t* keyCodes, uint8_t* outFlags) {
1117 bool result = false;
1118 size_t numMappers = mMappers.size();
1119 for (size_t i = 0; i < numMappers; i++) {
1120 InputMapper* mapper = mMappers[i];
1121 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1122 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1123 }
1124 }
1125 return result;
1126}
1127
1128void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1129 int32_t token) {
1130 size_t numMappers = mMappers.size();
1131 for (size_t i = 0; i < numMappers; i++) {
1132 InputMapper* mapper = mMappers[i];
1133 mapper->vibrate(pattern, patternSize, repeat, token);
1134 }
1135}
1136
1137void InputDevice::cancelVibrate(int32_t token) {
1138 size_t numMappers = mMappers.size();
1139 for (size_t i = 0; i < numMappers; i++) {
1140 InputMapper* mapper = mMappers[i];
1141 mapper->cancelVibrate(token);
1142 }
1143}
1144
Jeff Brownc9aa6282015-02-11 19:03:28 -08001145void InputDevice::cancelTouch(nsecs_t when) {
1146 size_t numMappers = mMappers.size();
1147 for (size_t i = 0; i < numMappers; i++) {
1148 InputMapper* mapper = mMappers[i];
1149 mapper->cancelTouch(when);
1150 }
1151}
1152
Michael Wrightd02c5b62014-02-10 15:10:22 -08001153int32_t InputDevice::getMetaState() {
1154 int32_t result = 0;
1155 size_t numMappers = mMappers.size();
1156 for (size_t i = 0; i < numMappers; i++) {
1157 InputMapper* mapper = mMappers[i];
1158 result |= mapper->getMetaState();
1159 }
1160 return result;
1161}
1162
1163void InputDevice::fadePointer() {
1164 size_t numMappers = mMappers.size();
1165 for (size_t i = 0; i < numMappers; i++) {
1166 InputMapper* mapper = mMappers[i];
1167 mapper->fadePointer();
1168 }
1169}
1170
1171void InputDevice::bumpGeneration() {
1172 mGeneration = mContext->bumpGeneration();
1173}
1174
1175void InputDevice::notifyReset(nsecs_t when) {
1176 NotifyDeviceResetArgs args(when, mId);
1177 mContext->getListener()->notifyDeviceReset(&args);
1178}
1179
1180
1181// --- CursorButtonAccumulator ---
1182
1183CursorButtonAccumulator::CursorButtonAccumulator() {
1184 clearButtons();
1185}
1186
1187void CursorButtonAccumulator::reset(InputDevice* device) {
1188 mBtnLeft = device->isKeyPressed(BTN_LEFT);
1189 mBtnRight = device->isKeyPressed(BTN_RIGHT);
1190 mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
1191 mBtnBack = device->isKeyPressed(BTN_BACK);
1192 mBtnSide = device->isKeyPressed(BTN_SIDE);
1193 mBtnForward = device->isKeyPressed(BTN_FORWARD);
1194 mBtnExtra = device->isKeyPressed(BTN_EXTRA);
1195 mBtnTask = device->isKeyPressed(BTN_TASK);
1196}
1197
1198void CursorButtonAccumulator::clearButtons() {
1199 mBtnLeft = 0;
1200 mBtnRight = 0;
1201 mBtnMiddle = 0;
1202 mBtnBack = 0;
1203 mBtnSide = 0;
1204 mBtnForward = 0;
1205 mBtnExtra = 0;
1206 mBtnTask = 0;
1207}
1208
1209void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1210 if (rawEvent->type == EV_KEY) {
1211 switch (rawEvent->code) {
1212 case BTN_LEFT:
1213 mBtnLeft = rawEvent->value;
1214 break;
1215 case BTN_RIGHT:
1216 mBtnRight = rawEvent->value;
1217 break;
1218 case BTN_MIDDLE:
1219 mBtnMiddle = rawEvent->value;
1220 break;
1221 case BTN_BACK:
1222 mBtnBack = rawEvent->value;
1223 break;
1224 case BTN_SIDE:
1225 mBtnSide = rawEvent->value;
1226 break;
1227 case BTN_FORWARD:
1228 mBtnForward = rawEvent->value;
1229 break;
1230 case BTN_EXTRA:
1231 mBtnExtra = rawEvent->value;
1232 break;
1233 case BTN_TASK:
1234 mBtnTask = rawEvent->value;
1235 break;
1236 }
1237 }
1238}
1239
1240uint32_t CursorButtonAccumulator::getButtonState() const {
1241 uint32_t result = 0;
1242 if (mBtnLeft) {
1243 result |= AMOTION_EVENT_BUTTON_PRIMARY;
1244 }
1245 if (mBtnRight) {
1246 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1247 }
1248 if (mBtnMiddle) {
1249 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1250 }
1251 if (mBtnBack || mBtnSide) {
1252 result |= AMOTION_EVENT_BUTTON_BACK;
1253 }
1254 if (mBtnForward || mBtnExtra) {
1255 result |= AMOTION_EVENT_BUTTON_FORWARD;
1256 }
1257 return result;
1258}
1259
1260
1261// --- CursorMotionAccumulator ---
1262
1263CursorMotionAccumulator::CursorMotionAccumulator() {
1264 clearRelativeAxes();
1265}
1266
1267void CursorMotionAccumulator::reset(InputDevice* device) {
1268 clearRelativeAxes();
1269}
1270
1271void CursorMotionAccumulator::clearRelativeAxes() {
1272 mRelX = 0;
1273 mRelY = 0;
1274}
1275
1276void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1277 if (rawEvent->type == EV_REL) {
1278 switch (rawEvent->code) {
1279 case REL_X:
1280 mRelX = rawEvent->value;
1281 break;
1282 case REL_Y:
1283 mRelY = rawEvent->value;
1284 break;
1285 }
1286 }
1287}
1288
1289void CursorMotionAccumulator::finishSync() {
1290 clearRelativeAxes();
1291}
1292
1293
1294// --- CursorScrollAccumulator ---
1295
1296CursorScrollAccumulator::CursorScrollAccumulator() :
1297 mHaveRelWheel(false), mHaveRelHWheel(false) {
1298 clearRelativeAxes();
1299}
1300
1301void CursorScrollAccumulator::configure(InputDevice* device) {
1302 mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1303 mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1304}
1305
1306void CursorScrollAccumulator::reset(InputDevice* device) {
1307 clearRelativeAxes();
1308}
1309
1310void CursorScrollAccumulator::clearRelativeAxes() {
1311 mRelWheel = 0;
1312 mRelHWheel = 0;
1313}
1314
1315void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
1316 if (rawEvent->type == EV_REL) {
1317 switch (rawEvent->code) {
1318 case REL_WHEEL:
1319 mRelWheel = rawEvent->value;
1320 break;
1321 case REL_HWHEEL:
1322 mRelHWheel = rawEvent->value;
1323 break;
1324 }
1325 }
1326}
1327
1328void CursorScrollAccumulator::finishSync() {
1329 clearRelativeAxes();
1330}
1331
1332
1333// --- TouchButtonAccumulator ---
1334
1335TouchButtonAccumulator::TouchButtonAccumulator() :
1336 mHaveBtnTouch(false), mHaveStylus(false) {
1337 clearButtons();
1338}
1339
1340void TouchButtonAccumulator::configure(InputDevice* device) {
1341 mHaveBtnTouch = device->hasKey(BTN_TOUCH);
1342 mHaveStylus = device->hasKey(BTN_TOOL_PEN)
1343 || device->hasKey(BTN_TOOL_RUBBER)
1344 || device->hasKey(BTN_TOOL_BRUSH)
1345 || device->hasKey(BTN_TOOL_PENCIL)
1346 || device->hasKey(BTN_TOOL_AIRBRUSH);
1347}
1348
1349void TouchButtonAccumulator::reset(InputDevice* device) {
1350 mBtnTouch = device->isKeyPressed(BTN_TOUCH);
1351 mBtnStylus = device->isKeyPressed(BTN_STYLUS);
Michael Wright842500e2015-03-13 17:32:02 -07001352 // BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
1353 mBtnStylus2 =
1354 device->isKeyPressed(BTN_STYLUS2) || device->isKeyPressed(BTN_0);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001355 mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
1356 mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
1357 mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
1358 mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
1359 mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
1360 mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
1361 mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
1362 mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
1363 mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
1364 mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
1365 mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
1366}
1367
1368void TouchButtonAccumulator::clearButtons() {
1369 mBtnTouch = 0;
1370 mBtnStylus = 0;
1371 mBtnStylus2 = 0;
1372 mBtnToolFinger = 0;
1373 mBtnToolPen = 0;
1374 mBtnToolRubber = 0;
1375 mBtnToolBrush = 0;
1376 mBtnToolPencil = 0;
1377 mBtnToolAirbrush = 0;
1378 mBtnToolMouse = 0;
1379 mBtnToolLens = 0;
1380 mBtnToolDoubleTap = 0;
1381 mBtnToolTripleTap = 0;
1382 mBtnToolQuadTap = 0;
1383}
1384
1385void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1386 if (rawEvent->type == EV_KEY) {
1387 switch (rawEvent->code) {
1388 case BTN_TOUCH:
1389 mBtnTouch = rawEvent->value;
1390 break;
1391 case BTN_STYLUS:
1392 mBtnStylus = rawEvent->value;
1393 break;
1394 case BTN_STYLUS2:
Michael Wright842500e2015-03-13 17:32:02 -07001395 case BTN_0:// BTN_0 is what gets mapped for the HID usage Digitizers.SecondaryBarrelSwitch
Michael Wrightd02c5b62014-02-10 15:10:22 -08001396 mBtnStylus2 = rawEvent->value;
1397 break;
1398 case BTN_TOOL_FINGER:
1399 mBtnToolFinger = rawEvent->value;
1400 break;
1401 case BTN_TOOL_PEN:
1402 mBtnToolPen = rawEvent->value;
1403 break;
1404 case BTN_TOOL_RUBBER:
1405 mBtnToolRubber = rawEvent->value;
1406 break;
1407 case BTN_TOOL_BRUSH:
1408 mBtnToolBrush = rawEvent->value;
1409 break;
1410 case BTN_TOOL_PENCIL:
1411 mBtnToolPencil = rawEvent->value;
1412 break;
1413 case BTN_TOOL_AIRBRUSH:
1414 mBtnToolAirbrush = rawEvent->value;
1415 break;
1416 case BTN_TOOL_MOUSE:
1417 mBtnToolMouse = rawEvent->value;
1418 break;
1419 case BTN_TOOL_LENS:
1420 mBtnToolLens = rawEvent->value;
1421 break;
1422 case BTN_TOOL_DOUBLETAP:
1423 mBtnToolDoubleTap = rawEvent->value;
1424 break;
1425 case BTN_TOOL_TRIPLETAP:
1426 mBtnToolTripleTap = rawEvent->value;
1427 break;
1428 case BTN_TOOL_QUADTAP:
1429 mBtnToolQuadTap = rawEvent->value;
1430 break;
1431 }
1432 }
1433}
1434
1435uint32_t TouchButtonAccumulator::getButtonState() const {
1436 uint32_t result = 0;
1437 if (mBtnStylus) {
1438 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1439 }
1440 if (mBtnStylus2) {
1441 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1442 }
1443 return result;
1444}
1445
1446int32_t TouchButtonAccumulator::getToolType() const {
1447 if (mBtnToolMouse || mBtnToolLens) {
1448 return AMOTION_EVENT_TOOL_TYPE_MOUSE;
1449 }
1450 if (mBtnToolRubber) {
1451 return AMOTION_EVENT_TOOL_TYPE_ERASER;
1452 }
1453 if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
1454 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1455 }
1456 if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
1457 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1458 }
1459 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1460}
1461
1462bool TouchButtonAccumulator::isToolActive() const {
1463 return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
1464 || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
1465 || mBtnToolMouse || mBtnToolLens
1466 || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
1467}
1468
1469bool TouchButtonAccumulator::isHovering() const {
1470 return mHaveBtnTouch && !mBtnTouch;
1471}
1472
1473bool TouchButtonAccumulator::hasStylus() const {
1474 return mHaveStylus;
1475}
1476
1477
1478// --- RawPointerAxes ---
1479
1480RawPointerAxes::RawPointerAxes() {
1481 clear();
1482}
1483
1484void RawPointerAxes::clear() {
1485 x.clear();
1486 y.clear();
1487 pressure.clear();
1488 touchMajor.clear();
1489 touchMinor.clear();
1490 toolMajor.clear();
1491 toolMinor.clear();
1492 orientation.clear();
1493 distance.clear();
1494 tiltX.clear();
1495 tiltY.clear();
1496 trackingId.clear();
1497 slot.clear();
1498}
1499
1500
1501// --- RawPointerData ---
1502
1503RawPointerData::RawPointerData() {
1504 clear();
1505}
1506
1507void RawPointerData::clear() {
1508 pointerCount = 0;
1509 clearIdBits();
1510}
1511
1512void RawPointerData::copyFrom(const RawPointerData& other) {
1513 pointerCount = other.pointerCount;
1514 hoveringIdBits = other.hoveringIdBits;
1515 touchingIdBits = other.touchingIdBits;
1516
1517 for (uint32_t i = 0; i < pointerCount; i++) {
1518 pointers[i] = other.pointers[i];
1519
1520 int id = pointers[i].id;
1521 idToIndex[id] = other.idToIndex[id];
1522 }
1523}
1524
1525void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
1526 float x = 0, y = 0;
1527 uint32_t count = touchingIdBits.count();
1528 if (count) {
1529 for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
1530 uint32_t id = idBits.clearFirstMarkedBit();
1531 const Pointer& pointer = pointerForId(id);
1532 x += pointer.x;
1533 y += pointer.y;
1534 }
1535 x /= count;
1536 y /= count;
1537 }
1538 *outX = x;
1539 *outY = y;
1540}
1541
1542
1543// --- CookedPointerData ---
1544
1545CookedPointerData::CookedPointerData() {
1546 clear();
1547}
1548
1549void CookedPointerData::clear() {
1550 pointerCount = 0;
1551 hoveringIdBits.clear();
1552 touchingIdBits.clear();
1553}
1554
1555void CookedPointerData::copyFrom(const CookedPointerData& other) {
1556 pointerCount = other.pointerCount;
1557 hoveringIdBits = other.hoveringIdBits;
1558 touchingIdBits = other.touchingIdBits;
1559
1560 for (uint32_t i = 0; i < pointerCount; i++) {
1561 pointerProperties[i].copyFrom(other.pointerProperties[i]);
1562 pointerCoords[i].copyFrom(other.pointerCoords[i]);
1563
1564 int id = pointerProperties[i].id;
1565 idToIndex[id] = other.idToIndex[id];
1566 }
1567}
1568
1569
1570// --- SingleTouchMotionAccumulator ---
1571
1572SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1573 clearAbsoluteAxes();
1574}
1575
1576void SingleTouchMotionAccumulator::reset(InputDevice* device) {
1577 mAbsX = device->getAbsoluteAxisValue(ABS_X);
1578 mAbsY = device->getAbsoluteAxisValue(ABS_Y);
1579 mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
1580 mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
1581 mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
1582 mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
1583 mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
1584}
1585
1586void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1587 mAbsX = 0;
1588 mAbsY = 0;
1589 mAbsPressure = 0;
1590 mAbsToolWidth = 0;
1591 mAbsDistance = 0;
1592 mAbsTiltX = 0;
1593 mAbsTiltY = 0;
1594}
1595
1596void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1597 if (rawEvent->type == EV_ABS) {
1598 switch (rawEvent->code) {
1599 case ABS_X:
1600 mAbsX = rawEvent->value;
1601 break;
1602 case ABS_Y:
1603 mAbsY = rawEvent->value;
1604 break;
1605 case ABS_PRESSURE:
1606 mAbsPressure = rawEvent->value;
1607 break;
1608 case ABS_TOOL_WIDTH:
1609 mAbsToolWidth = rawEvent->value;
1610 break;
1611 case ABS_DISTANCE:
1612 mAbsDistance = rawEvent->value;
1613 break;
1614 case ABS_TILT_X:
1615 mAbsTiltX = rawEvent->value;
1616 break;
1617 case ABS_TILT_Y:
1618 mAbsTiltY = rawEvent->value;
1619 break;
1620 }
1621 }
1622}
1623
1624
1625// --- MultiTouchMotionAccumulator ---
1626
1627MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
1628 mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false),
1629 mHaveStylus(false) {
1630}
1631
1632MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1633 delete[] mSlots;
1634}
1635
1636void MultiTouchMotionAccumulator::configure(InputDevice* device,
1637 size_t slotCount, bool usingSlotsProtocol) {
1638 mSlotCount = slotCount;
1639 mUsingSlotsProtocol = usingSlotsProtocol;
1640 mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
1641
1642 delete[] mSlots;
1643 mSlots = new Slot[slotCount];
1644}
1645
1646void MultiTouchMotionAccumulator::reset(InputDevice* device) {
1647 // Unfortunately there is no way to read the initial contents of the slots.
1648 // So when we reset the accumulator, we must assume they are all zeroes.
1649 if (mUsingSlotsProtocol) {
1650 // Query the driver for the current slot index and use it as the initial slot
1651 // before we start reading events from the device. It is possible that the
1652 // current slot index will not be the same as it was when the first event was
1653 // written into the evdev buffer, which means the input mapper could start
1654 // out of sync with the initial state of the events in the evdev buffer.
1655 // In the extremely unlikely case that this happens, the data from
1656 // two slots will be confused until the next ABS_MT_SLOT event is received.
1657 // This can cause the touch point to "jump", but at least there will be
1658 // no stuck touches.
1659 int32_t initialSlot;
1660 status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
1661 ABS_MT_SLOT, &initialSlot);
1662 if (status) {
1663 ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
1664 initialSlot = -1;
1665 }
1666 clearSlots(initialSlot);
1667 } else {
1668 clearSlots(-1);
1669 }
1670}
1671
1672void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
1673 if (mSlots) {
1674 for (size_t i = 0; i < mSlotCount; i++) {
1675 mSlots[i].clear();
1676 }
1677 }
1678 mCurrentSlot = initialSlot;
1679}
1680
1681void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1682 if (rawEvent->type == EV_ABS) {
1683 bool newSlot = false;
1684 if (mUsingSlotsProtocol) {
1685 if (rawEvent->code == ABS_MT_SLOT) {
1686 mCurrentSlot = rawEvent->value;
1687 newSlot = true;
1688 }
1689 } else if (mCurrentSlot < 0) {
1690 mCurrentSlot = 0;
1691 }
1692
1693 if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1694#if DEBUG_POINTERS
1695 if (newSlot) {
1696 ALOGW("MultiTouch device emitted invalid slot index %d but it "
1697 "should be between 0 and %d; ignoring this slot.",
1698 mCurrentSlot, mSlotCount - 1);
1699 }
1700#endif
1701 } else {
1702 Slot* slot = &mSlots[mCurrentSlot];
1703
1704 switch (rawEvent->code) {
1705 case ABS_MT_POSITION_X:
1706 slot->mInUse = true;
1707 slot->mAbsMTPositionX = rawEvent->value;
1708 break;
1709 case ABS_MT_POSITION_Y:
1710 slot->mInUse = true;
1711 slot->mAbsMTPositionY = rawEvent->value;
1712 break;
1713 case ABS_MT_TOUCH_MAJOR:
1714 slot->mInUse = true;
1715 slot->mAbsMTTouchMajor = rawEvent->value;
1716 break;
1717 case ABS_MT_TOUCH_MINOR:
1718 slot->mInUse = true;
1719 slot->mAbsMTTouchMinor = rawEvent->value;
1720 slot->mHaveAbsMTTouchMinor = true;
1721 break;
1722 case ABS_MT_WIDTH_MAJOR:
1723 slot->mInUse = true;
1724 slot->mAbsMTWidthMajor = rawEvent->value;
1725 break;
1726 case ABS_MT_WIDTH_MINOR:
1727 slot->mInUse = true;
1728 slot->mAbsMTWidthMinor = rawEvent->value;
1729 slot->mHaveAbsMTWidthMinor = true;
1730 break;
1731 case ABS_MT_ORIENTATION:
1732 slot->mInUse = true;
1733 slot->mAbsMTOrientation = rawEvent->value;
1734 break;
1735 case ABS_MT_TRACKING_ID:
1736 if (mUsingSlotsProtocol && rawEvent->value < 0) {
1737 // The slot is no longer in use but it retains its previous contents,
1738 // which may be reused for subsequent touches.
1739 slot->mInUse = false;
1740 } else {
1741 slot->mInUse = true;
1742 slot->mAbsMTTrackingId = rawEvent->value;
1743 }
1744 break;
1745 case ABS_MT_PRESSURE:
1746 slot->mInUse = true;
1747 slot->mAbsMTPressure = rawEvent->value;
1748 break;
1749 case ABS_MT_DISTANCE:
1750 slot->mInUse = true;
1751 slot->mAbsMTDistance = rawEvent->value;
1752 break;
1753 case ABS_MT_TOOL_TYPE:
1754 slot->mInUse = true;
1755 slot->mAbsMTToolType = rawEvent->value;
1756 slot->mHaveAbsMTToolType = true;
1757 break;
1758 }
1759 }
1760 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
1761 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1762 mCurrentSlot += 1;
1763 }
1764}
1765
1766void MultiTouchMotionAccumulator::finishSync() {
1767 if (!mUsingSlotsProtocol) {
1768 clearSlots(-1);
1769 }
1770}
1771
1772bool MultiTouchMotionAccumulator::hasStylus() const {
1773 return mHaveStylus;
1774}
1775
1776
1777// --- MultiTouchMotionAccumulator::Slot ---
1778
1779MultiTouchMotionAccumulator::Slot::Slot() {
1780 clear();
1781}
1782
1783void MultiTouchMotionAccumulator::Slot::clear() {
1784 mInUse = false;
1785 mHaveAbsMTTouchMinor = false;
1786 mHaveAbsMTWidthMinor = false;
1787 mHaveAbsMTToolType = false;
1788 mAbsMTPositionX = 0;
1789 mAbsMTPositionY = 0;
1790 mAbsMTTouchMajor = 0;
1791 mAbsMTTouchMinor = 0;
1792 mAbsMTWidthMajor = 0;
1793 mAbsMTWidthMinor = 0;
1794 mAbsMTOrientation = 0;
1795 mAbsMTTrackingId = -1;
1796 mAbsMTPressure = 0;
1797 mAbsMTDistance = 0;
1798 mAbsMTToolType = 0;
1799}
1800
1801int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1802 if (mHaveAbsMTToolType) {
1803 switch (mAbsMTToolType) {
1804 case MT_TOOL_FINGER:
1805 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1806 case MT_TOOL_PEN:
1807 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1808 }
1809 }
1810 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1811}
1812
1813
1814// --- InputMapper ---
1815
1816InputMapper::InputMapper(InputDevice* device) :
1817 mDevice(device), mContext(device->getContext()) {
1818}
1819
1820InputMapper::~InputMapper() {
1821}
1822
1823void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1824 info->addSource(getSources());
1825}
1826
1827void InputMapper::dump(String8& dump) {
1828}
1829
1830void InputMapper::configure(nsecs_t when,
1831 const InputReaderConfiguration* config, uint32_t changes) {
1832}
1833
1834void InputMapper::reset(nsecs_t when) {
1835}
1836
1837void InputMapper::timeoutExpired(nsecs_t when) {
1838}
1839
1840int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1841 return AKEY_STATE_UNKNOWN;
1842}
1843
1844int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1845 return AKEY_STATE_UNKNOWN;
1846}
1847
1848int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1849 return AKEY_STATE_UNKNOWN;
1850}
1851
1852bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1853 const int32_t* keyCodes, uint8_t* outFlags) {
1854 return false;
1855}
1856
1857void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1858 int32_t token) {
1859}
1860
1861void InputMapper::cancelVibrate(int32_t token) {
1862}
1863
Jeff Brownc9aa6282015-02-11 19:03:28 -08001864void InputMapper::cancelTouch(nsecs_t when) {
1865}
1866
Michael Wrightd02c5b62014-02-10 15:10:22 -08001867int32_t InputMapper::getMetaState() {
1868 return 0;
1869}
1870
Michael Wright842500e2015-03-13 17:32:02 -07001871void InputMapper::updateExternalStylusState(const StylusState& state) {
1872
1873}
1874
Michael Wrightd02c5b62014-02-10 15:10:22 -08001875void InputMapper::fadePointer() {
1876}
1877
1878status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
1879 return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
1880}
1881
1882void InputMapper::bumpGeneration() {
1883 mDevice->bumpGeneration();
1884}
1885
1886void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
1887 const RawAbsoluteAxisInfo& axis, const char* name) {
1888 if (axis.valid) {
1889 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
1890 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
1891 } else {
1892 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
1893 }
1894}
1895
Michael Wright842500e2015-03-13 17:32:02 -07001896void InputMapper::dumpStylusState(String8& dump, const StylusState& state) {
1897 dump.appendFormat(INDENT4 "When: %" PRId64 "\n", state.when);
1898 dump.appendFormat(INDENT4 "Pressure: %f\n", state.pressure);
1899 dump.appendFormat(INDENT4 "Button State: 0x%08x\n", state.buttons);
1900 dump.appendFormat(INDENT4 "Tool Type: %" PRId32 "\n", state.toolType);
1901}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001902
1903// --- SwitchInputMapper ---
1904
1905SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
Michael Wrightbcbf97e2014-08-29 14:31:32 -07001906 InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08001907}
1908
1909SwitchInputMapper::~SwitchInputMapper() {
1910}
1911
1912uint32_t SwitchInputMapper::getSources() {
1913 return AINPUT_SOURCE_SWITCH;
1914}
1915
1916void SwitchInputMapper::process(const RawEvent* rawEvent) {
1917 switch (rawEvent->type) {
1918 case EV_SW:
1919 processSwitch(rawEvent->code, rawEvent->value);
1920 break;
1921
1922 case EV_SYN:
1923 if (rawEvent->code == SYN_REPORT) {
1924 sync(rawEvent->when);
1925 }
1926 }
1927}
1928
1929void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
1930 if (switchCode >= 0 && switchCode < 32) {
1931 if (switchValue) {
Michael Wrightbcbf97e2014-08-29 14:31:32 -07001932 mSwitchValues |= 1 << switchCode;
1933 } else {
1934 mSwitchValues &= ~(1 << switchCode);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001935 }
1936 mUpdatedSwitchMask |= 1 << switchCode;
1937 }
1938}
1939
1940void SwitchInputMapper::sync(nsecs_t when) {
1941 if (mUpdatedSwitchMask) {
Michael Wright3da3b842014-08-29 16:16:26 -07001942 uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
Michael Wrightbcbf97e2014-08-29 14:31:32 -07001943 NotifySwitchArgs args(when, 0, updatedSwitchValues, mUpdatedSwitchMask);
Michael Wrightd02c5b62014-02-10 15:10:22 -08001944 getListener()->notifySwitch(&args);
1945
Michael Wrightd02c5b62014-02-10 15:10:22 -08001946 mUpdatedSwitchMask = 0;
1947 }
1948}
1949
1950int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1951 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1952}
1953
Michael Wrightbcbf97e2014-08-29 14:31:32 -07001954void SwitchInputMapper::dump(String8& dump) {
1955 dump.append(INDENT2 "Switch Input Mapper:\n");
1956 dump.appendFormat(INDENT3 "SwitchValues: %x\n", mSwitchValues);
1957}
Michael Wrightd02c5b62014-02-10 15:10:22 -08001958
1959// --- VibratorInputMapper ---
1960
1961VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
1962 InputMapper(device), mVibrating(false) {
1963}
1964
1965VibratorInputMapper::~VibratorInputMapper() {
1966}
1967
1968uint32_t VibratorInputMapper::getSources() {
1969 return 0;
1970}
1971
1972void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1973 InputMapper::populateDeviceInfo(info);
1974
1975 info->setVibrator(true);
1976}
1977
1978void VibratorInputMapper::process(const RawEvent* rawEvent) {
1979 // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
1980}
1981
1982void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
1983 int32_t token) {
1984#if DEBUG_VIBRATOR
1985 String8 patternStr;
1986 for (size_t i = 0; i < patternSize; i++) {
1987 if (i != 0) {
1988 patternStr.append(", ");
1989 }
1990 patternStr.appendFormat("%lld", pattern[i]);
1991 }
1992 ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
1993 getDeviceId(), patternStr.string(), repeat, token);
1994#endif
1995
1996 mVibrating = true;
1997 memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
1998 mPatternSize = patternSize;
1999 mRepeat = repeat;
2000 mToken = token;
2001 mIndex = -1;
2002
2003 nextStep();
2004}
2005
2006void VibratorInputMapper::cancelVibrate(int32_t token) {
2007#if DEBUG_VIBRATOR
2008 ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
2009#endif
2010
2011 if (mVibrating && mToken == token) {
2012 stopVibrating();
2013 }
2014}
2015
2016void VibratorInputMapper::timeoutExpired(nsecs_t when) {
2017 if (mVibrating) {
2018 if (when >= mNextStepTime) {
2019 nextStep();
2020 } else {
2021 getContext()->requestTimeoutAtTime(mNextStepTime);
2022 }
2023 }
2024}
2025
2026void VibratorInputMapper::nextStep() {
2027 mIndex += 1;
2028 if (size_t(mIndex) >= mPatternSize) {
2029 if (mRepeat < 0) {
2030 // We are done.
2031 stopVibrating();
2032 return;
2033 }
2034 mIndex = mRepeat;
2035 }
2036
2037 bool vibratorOn = mIndex & 1;
2038 nsecs_t duration = mPattern[mIndex];
2039 if (vibratorOn) {
2040#if DEBUG_VIBRATOR
2041 ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld",
2042 getDeviceId(), duration);
2043#endif
2044 getEventHub()->vibrate(getDeviceId(), duration);
2045 } else {
2046#if DEBUG_VIBRATOR
2047 ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
2048#endif
2049 getEventHub()->cancelVibrate(getDeviceId());
2050 }
2051 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
2052 mNextStepTime = now + duration;
2053 getContext()->requestTimeoutAtTime(mNextStepTime);
2054#if DEBUG_VIBRATOR
2055 ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
2056#endif
2057}
2058
2059void VibratorInputMapper::stopVibrating() {
2060 mVibrating = false;
2061#if DEBUG_VIBRATOR
2062 ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
2063#endif
2064 getEventHub()->cancelVibrate(getDeviceId());
2065}
2066
2067void VibratorInputMapper::dump(String8& dump) {
2068 dump.append(INDENT2 "Vibrator Input Mapper:\n");
2069 dump.appendFormat(INDENT3 "Vibrating: %s\n", toString(mVibrating));
2070}
2071
2072
2073// --- KeyboardInputMapper ---
2074
2075KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
2076 uint32_t source, int32_t keyboardType) :
2077 InputMapper(device), mSource(source),
2078 mKeyboardType(keyboardType) {
2079}
2080
2081KeyboardInputMapper::~KeyboardInputMapper() {
2082}
2083
2084uint32_t KeyboardInputMapper::getSources() {
2085 return mSource;
2086}
2087
2088void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2089 InputMapper::populateDeviceInfo(info);
2090
2091 info->setKeyboardType(mKeyboardType);
2092 info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
2093}
2094
2095void KeyboardInputMapper::dump(String8& dump) {
2096 dump.append(INDENT2 "Keyboard Input Mapper:\n");
2097 dumpParameters(dump);
2098 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
2099 dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
Mark Salyzyn41d2f802014-03-18 10:59:23 -07002100 dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
Michael Wrightd02c5b62014-02-10 15:10:22 -08002101 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
Mark Salyzyn41d2f802014-03-18 10:59:23 -07002102 dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002103}
2104
2105
2106void KeyboardInputMapper::configure(nsecs_t when,
2107 const InputReaderConfiguration* config, uint32_t changes) {
2108 InputMapper::configure(when, config, changes);
2109
2110 if (!changes) { // first time only
2111 // Configure basic parameters.
2112 configureParameters();
2113 }
2114
2115 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
2116 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
2117 DisplayViewport v;
2118 if (config->getDisplayInfo(false /*external*/, &v)) {
2119 mOrientation = v.orientation;
2120 } else {
2121 mOrientation = DISPLAY_ORIENTATION_0;
2122 }
2123 } else {
2124 mOrientation = DISPLAY_ORIENTATION_0;
2125 }
2126 }
2127}
2128
2129void KeyboardInputMapper::configureParameters() {
2130 mParameters.orientationAware = false;
2131 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
2132 mParameters.orientationAware);
2133
2134 mParameters.hasAssociatedDisplay = false;
2135 if (mParameters.orientationAware) {
2136 mParameters.hasAssociatedDisplay = true;
2137 }
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002138
2139 mParameters.handlesKeyRepeat = false;
2140 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.handlesKeyRepeat"),
2141 mParameters.handlesKeyRepeat);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002142}
2143
2144void KeyboardInputMapper::dumpParameters(String8& dump) {
2145 dump.append(INDENT3 "Parameters:\n");
2146 dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
2147 toString(mParameters.hasAssociatedDisplay));
2148 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2149 toString(mParameters.orientationAware));
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002150 dump.appendFormat(INDENT4 "HandlesKeyRepeat: %s\n",
2151 toString(mParameters.handlesKeyRepeat));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002152}
2153
2154void KeyboardInputMapper::reset(nsecs_t when) {
2155 mMetaState = AMETA_NONE;
2156 mDownTime = 0;
2157 mKeyDowns.clear();
2158 mCurrentHidUsage = 0;
2159
2160 resetLedState();
2161
2162 InputMapper::reset(when);
2163}
2164
2165void KeyboardInputMapper::process(const RawEvent* rawEvent) {
2166 switch (rawEvent->type) {
2167 case EV_KEY: {
2168 int32_t scanCode = rawEvent->code;
2169 int32_t usageCode = mCurrentHidUsage;
2170 mCurrentHidUsage = 0;
2171
2172 if (isKeyboardOrGamepadKey(scanCode)) {
2173 int32_t keyCode;
2174 uint32_t flags;
2175 if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
2176 keyCode = AKEYCODE_UNKNOWN;
2177 flags = 0;
2178 }
2179 processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
2180 }
2181 break;
2182 }
2183 case EV_MSC: {
2184 if (rawEvent->code == MSC_SCAN) {
2185 mCurrentHidUsage = rawEvent->value;
2186 }
2187 break;
2188 }
2189 case EV_SYN: {
2190 if (rawEvent->code == SYN_REPORT) {
2191 mCurrentHidUsage = 0;
2192 }
2193 }
2194 }
2195}
2196
2197bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
2198 return scanCode < BTN_MOUSE
2199 || scanCode >= KEY_OK
2200 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
2201 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
2202}
2203
2204void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
2205 int32_t scanCode, uint32_t policyFlags) {
2206
2207 if (down) {
2208 // Rotate key codes according to orientation if needed.
2209 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
2210 keyCode = rotateKeyCode(keyCode, mOrientation);
2211 }
2212
2213 // Add key down.
2214 ssize_t keyDownIndex = findKeyDown(scanCode);
2215 if (keyDownIndex >= 0) {
2216 // key repeat, be sure to use same keycode as before in case of rotation
2217 keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
2218 } else {
2219 // key down
2220 if ((policyFlags & POLICY_FLAG_VIRTUAL)
2221 && mContext->shouldDropVirtualKey(when,
2222 getDevice(), keyCode, scanCode)) {
2223 return;
2224 }
Jeff Brownc9aa6282015-02-11 19:03:28 -08002225 if (policyFlags & POLICY_FLAG_GESTURE) {
2226 mDevice->cancelTouch(when);
2227 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08002228
2229 mKeyDowns.push();
2230 KeyDown& keyDown = mKeyDowns.editTop();
2231 keyDown.keyCode = keyCode;
2232 keyDown.scanCode = scanCode;
2233 }
2234
2235 mDownTime = when;
2236 } else {
2237 // Remove key down.
2238 ssize_t keyDownIndex = findKeyDown(scanCode);
2239 if (keyDownIndex >= 0) {
2240 // key up, be sure to use same keycode as before in case of rotation
2241 keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
2242 mKeyDowns.removeAt(size_t(keyDownIndex));
2243 } else {
2244 // key was not actually down
2245 ALOGI("Dropping key up from device %s because the key was not down. "
2246 "keyCode=%d, scanCode=%d",
2247 getDeviceName().string(), keyCode, scanCode);
2248 return;
2249 }
2250 }
2251
2252 int32_t oldMetaState = mMetaState;
2253 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
2254 bool metaStateChanged = oldMetaState != newMetaState;
2255 if (metaStateChanged) {
2256 mMetaState = newMetaState;
2257 updateLedState(false);
2258 }
2259
2260 nsecs_t downTime = mDownTime;
2261
2262 // Key down on external an keyboard should wake the device.
2263 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
2264 // For internal keyboards, the key layout file should specify the policy flags for
2265 // each wake key individually.
2266 // TODO: Use the input device configuration to control this behavior more finely.
Michael Wright872db4f2014-04-22 15:03:51 -07002267 if (down && getDevice()->isExternal()) {
2268 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002269 }
2270
Michael Wrightdcfcf5d2014-03-17 12:58:21 -07002271 if (mParameters.handlesKeyRepeat) {
2272 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
2273 }
2274
Michael Wrightd02c5b62014-02-10 15:10:22 -08002275 if (metaStateChanged) {
2276 getContext()->updateGlobalMetaState();
2277 }
2278
2279 if (down && !isMetaKey(keyCode)) {
2280 getContext()->fadePointer();
2281 }
2282
2283 NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
2284 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
2285 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
2286 getListener()->notifyKey(&args);
2287}
2288
2289ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
2290 size_t n = mKeyDowns.size();
2291 for (size_t i = 0; i < n; i++) {
2292 if (mKeyDowns[i].scanCode == scanCode) {
2293 return i;
2294 }
2295 }
2296 return -1;
2297}
2298
2299int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
2300 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
2301}
2302
2303int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2304 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2305}
2306
2307bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2308 const int32_t* keyCodes, uint8_t* outFlags) {
2309 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
2310}
2311
2312int32_t KeyboardInputMapper::getMetaState() {
2313 return mMetaState;
2314}
2315
2316void KeyboardInputMapper::resetLedState() {
2317 initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
2318 initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
2319 initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
2320
2321 updateLedState(true);
2322}
2323
2324void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
2325 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
2326 ledState.on = false;
2327}
2328
2329void KeyboardInputMapper::updateLedState(bool reset) {
2330 updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
2331 AMETA_CAPS_LOCK_ON, reset);
2332 updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
2333 AMETA_NUM_LOCK_ON, reset);
2334 updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
2335 AMETA_SCROLL_LOCK_ON, reset);
2336}
2337
2338void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
2339 int32_t led, int32_t modifier, bool reset) {
2340 if (ledState.avail) {
2341 bool desiredState = (mMetaState & modifier) != 0;
2342 if (reset || ledState.on != desiredState) {
2343 getEventHub()->setLedState(getDeviceId(), led, desiredState);
2344 ledState.on = desiredState;
2345 }
2346 }
2347}
2348
2349
2350// --- CursorInputMapper ---
2351
2352CursorInputMapper::CursorInputMapper(InputDevice* device) :
2353 InputMapper(device) {
2354}
2355
2356CursorInputMapper::~CursorInputMapper() {
2357}
2358
2359uint32_t CursorInputMapper::getSources() {
2360 return mSource;
2361}
2362
2363void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2364 InputMapper::populateDeviceInfo(info);
2365
2366 if (mParameters.mode == Parameters::MODE_POINTER) {
2367 float minX, minY, maxX, maxY;
2368 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
2369 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
2370 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
2371 }
2372 } else {
2373 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
2374 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
2375 }
2376 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2377
2378 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2379 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2380 }
2381 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2382 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
2383 }
2384}
2385
2386void CursorInputMapper::dump(String8& dump) {
2387 dump.append(INDENT2 "Cursor Input Mapper:\n");
2388 dumpParameters(dump);
2389 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
2390 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
2391 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
2392 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
2393 dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
2394 toString(mCursorScrollAccumulator.haveRelativeVWheel()));
2395 dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
2396 toString(mCursorScrollAccumulator.haveRelativeHWheel()));
2397 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
2398 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
2399 dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
2400 dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
2401 dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
Mark Salyzyn41d2f802014-03-18 10:59:23 -07002402 dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002403}
2404
2405void CursorInputMapper::configure(nsecs_t when,
2406 const InputReaderConfiguration* config, uint32_t changes) {
2407 InputMapper::configure(when, config, changes);
2408
2409 if (!changes) { // first time only
2410 mCursorScrollAccumulator.configure(getDevice());
2411
2412 // Configure basic parameters.
2413 configureParameters();
2414
2415 // Configure device mode.
2416 switch (mParameters.mode) {
2417 case Parameters::MODE_POINTER:
2418 mSource = AINPUT_SOURCE_MOUSE;
2419 mXPrecision = 1.0f;
2420 mYPrecision = 1.0f;
2421 mXScale = 1.0f;
2422 mYScale = 1.0f;
2423 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2424 break;
2425 case Parameters::MODE_NAVIGATION:
2426 mSource = AINPUT_SOURCE_TRACKBALL;
2427 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2428 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2429 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2430 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2431 break;
2432 }
2433
2434 mVWheelScale = 1.0f;
2435 mHWheelScale = 1.0f;
2436 }
2437
2438 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2439 mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
2440 mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
2441 mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
2442 }
2443
2444 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
2445 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
2446 DisplayViewport v;
2447 if (config->getDisplayInfo(false /*external*/, &v)) {
2448 mOrientation = v.orientation;
2449 } else {
2450 mOrientation = DISPLAY_ORIENTATION_0;
2451 }
2452 } else {
2453 mOrientation = DISPLAY_ORIENTATION_0;
2454 }
2455 bumpGeneration();
2456 }
2457}
2458
2459void CursorInputMapper::configureParameters() {
2460 mParameters.mode = Parameters::MODE_POINTER;
2461 String8 cursorModeString;
2462 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
2463 if (cursorModeString == "navigation") {
2464 mParameters.mode = Parameters::MODE_NAVIGATION;
2465 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
2466 ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
2467 }
2468 }
2469
2470 mParameters.orientationAware = false;
2471 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
2472 mParameters.orientationAware);
2473
2474 mParameters.hasAssociatedDisplay = false;
2475 if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
2476 mParameters.hasAssociatedDisplay = true;
2477 }
2478}
2479
2480void CursorInputMapper::dumpParameters(String8& dump) {
2481 dump.append(INDENT3 "Parameters:\n");
2482 dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
2483 toString(mParameters.hasAssociatedDisplay));
2484
2485 switch (mParameters.mode) {
2486 case Parameters::MODE_POINTER:
2487 dump.append(INDENT4 "Mode: pointer\n");
2488 break;
2489 case Parameters::MODE_NAVIGATION:
2490 dump.append(INDENT4 "Mode: navigation\n");
2491 break;
2492 default:
2493 ALOG_ASSERT(false);
2494 }
2495
2496 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2497 toString(mParameters.orientationAware));
2498}
2499
2500void CursorInputMapper::reset(nsecs_t when) {
2501 mButtonState = 0;
2502 mDownTime = 0;
2503
2504 mPointerVelocityControl.reset();
2505 mWheelXVelocityControl.reset();
2506 mWheelYVelocityControl.reset();
2507
2508 mCursorButtonAccumulator.reset(getDevice());
2509 mCursorMotionAccumulator.reset(getDevice());
2510 mCursorScrollAccumulator.reset(getDevice());
2511
2512 InputMapper::reset(when);
2513}
2514
2515void CursorInputMapper::process(const RawEvent* rawEvent) {
2516 mCursorButtonAccumulator.process(rawEvent);
2517 mCursorMotionAccumulator.process(rawEvent);
2518 mCursorScrollAccumulator.process(rawEvent);
2519
2520 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
2521 sync(rawEvent->when);
2522 }
2523}
2524
2525void CursorInputMapper::sync(nsecs_t when) {
2526 int32_t lastButtonState = mButtonState;
2527 int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
2528 mButtonState = currentButtonState;
2529
2530 bool wasDown = isPointerDown(lastButtonState);
2531 bool down = isPointerDown(currentButtonState);
2532 bool downChanged;
2533 if (!wasDown && down) {
2534 mDownTime = when;
2535 downChanged = true;
2536 } else if (wasDown && !down) {
2537 downChanged = true;
2538 } else {
2539 downChanged = false;
2540 }
2541 nsecs_t downTime = mDownTime;
2542 bool buttonsChanged = currentButtonState != lastButtonState;
2543 bool buttonsPressed = currentButtonState & ~lastButtonState;
2544
2545 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
2546 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
2547 bool moved = deltaX != 0 || deltaY != 0;
2548
2549 // Rotate delta according to orientation if needed.
2550 if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
2551 && (deltaX != 0.0f || deltaY != 0.0f)) {
2552 rotateDelta(mOrientation, &deltaX, &deltaY);
2553 }
2554
2555 // Move the pointer.
2556 PointerProperties pointerProperties;
2557 pointerProperties.clear();
2558 pointerProperties.id = 0;
2559 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
2560
2561 PointerCoords pointerCoords;
2562 pointerCoords.clear();
2563
2564 float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
2565 float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
2566 bool scrolled = vscroll != 0 || hscroll != 0;
2567
2568 mWheelYVelocityControl.move(when, NULL, &vscroll);
2569 mWheelXVelocityControl.move(when, &hscroll, NULL);
2570
2571 mPointerVelocityControl.move(when, &deltaX, &deltaY);
2572
2573 int32_t displayId;
2574 if (mPointerController != NULL) {
2575 if (moved || scrolled || buttonsChanged) {
2576 mPointerController->setPresentation(
2577 PointerControllerInterface::PRESENTATION_POINTER);
2578
2579 if (moved) {
2580 mPointerController->move(deltaX, deltaY);
2581 }
2582
2583 if (buttonsChanged) {
2584 mPointerController->setButtonState(currentButtonState);
2585 }
2586
2587 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
2588 }
2589
2590 float x, y;
2591 mPointerController->getPosition(&x, &y);
2592 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2593 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2594 displayId = ADISPLAY_ID_DEFAULT;
2595 } else {
2596 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
2597 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
2598 displayId = ADISPLAY_ID_NONE;
2599 }
2600
2601 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
2602
2603 // Moving an external trackball or mouse should wake the device.
2604 // We don't do this for internal cursor devices to prevent them from waking up
2605 // the device in your pocket.
2606 // TODO: Use the input device configuration to control this behavior more finely.
2607 uint32_t policyFlags = 0;
2608 if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
Michael Wright872db4f2014-04-22 15:03:51 -07002609 policyFlags |= POLICY_FLAG_WAKE;
Michael Wrightd02c5b62014-02-10 15:10:22 -08002610 }
2611
2612 // Synthesize key down from buttons if needed.
2613 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
2614 policyFlags, lastButtonState, currentButtonState);
2615
2616 // Send motion event.
2617 if (downChanged || moved || scrolled || buttonsChanged) {
2618 int32_t metaState = mContext->getGlobalMetaState();
2619 int32_t motionEventAction;
2620 if (downChanged) {
2621 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
2622 } else if (down || mPointerController == NULL) {
2623 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2624 } else {
2625 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
2626 }
2627
2628 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
2629 motionEventAction, 0, metaState, currentButtonState, 0,
2630 displayId, 1, &pointerProperties, &pointerCoords,
2631 mXPrecision, mYPrecision, downTime);
2632 getListener()->notifyMotion(&args);
2633
2634 // Send hover move after UP to tell the application that the mouse is hovering now.
2635 if (motionEventAction == AMOTION_EVENT_ACTION_UP
2636 && mPointerController != NULL) {
2637 NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
2638 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
2639 metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2640 displayId, 1, &pointerProperties, &pointerCoords,
2641 mXPrecision, mYPrecision, downTime);
2642 getListener()->notifyMotion(&hoverArgs);
2643 }
2644
2645 // Send scroll events.
2646 if (scrolled) {
2647 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2648 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2649
2650 NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
2651 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
2652 AMOTION_EVENT_EDGE_FLAG_NONE,
2653 displayId, 1, &pointerProperties, &pointerCoords,
2654 mXPrecision, mYPrecision, downTime);
2655 getListener()->notifyMotion(&scrollArgs);
2656 }
2657 }
2658
2659 // Synthesize key up from buttons if needed.
2660 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
2661 policyFlags, lastButtonState, currentButtonState);
2662
2663 mCursorMotionAccumulator.finishSync();
2664 mCursorScrollAccumulator.finishSync();
2665}
2666
2667int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2668 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2669 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2670 } else {
2671 return AKEY_STATE_UNKNOWN;
2672 }
2673}
2674
2675void CursorInputMapper::fadePointer() {
2676 if (mPointerController != NULL) {
2677 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
2678 }
2679}
2680
2681
2682// --- TouchInputMapper ---
2683
2684TouchInputMapper::TouchInputMapper(InputDevice* device) :
2685 InputMapper(device),
2686 mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
2687 mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
2688 mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
2689}
2690
2691TouchInputMapper::~TouchInputMapper() {
2692}
2693
2694uint32_t TouchInputMapper::getSources() {
2695 return mSource;
2696}
2697
2698void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2699 InputMapper::populateDeviceInfo(info);
2700
2701 if (mDeviceMode != DEVICE_MODE_DISABLED) {
2702 info->addMotionRange(mOrientedRanges.x);
2703 info->addMotionRange(mOrientedRanges.y);
2704 info->addMotionRange(mOrientedRanges.pressure);
2705
2706 if (mOrientedRanges.haveSize) {
2707 info->addMotionRange(mOrientedRanges.size);
2708 }
2709
2710 if (mOrientedRanges.haveTouchSize) {
2711 info->addMotionRange(mOrientedRanges.touchMajor);
2712 info->addMotionRange(mOrientedRanges.touchMinor);
2713 }
2714
2715 if (mOrientedRanges.haveToolSize) {
2716 info->addMotionRange(mOrientedRanges.toolMajor);
2717 info->addMotionRange(mOrientedRanges.toolMinor);
2718 }
2719
2720 if (mOrientedRanges.haveOrientation) {
2721 info->addMotionRange(mOrientedRanges.orientation);
2722 }
2723
2724 if (mOrientedRanges.haveDistance) {
2725 info->addMotionRange(mOrientedRanges.distance);
2726 }
2727
2728 if (mOrientedRanges.haveTilt) {
2729 info->addMotionRange(mOrientedRanges.tilt);
2730 }
2731
2732 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2733 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
2734 0.0f);
2735 }
2736 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2737 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
2738 0.0f);
2739 }
2740 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
2741 const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
2742 const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
2743 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
2744 x.fuzz, x.resolution);
2745 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
2746 y.fuzz, y.resolution);
2747 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
2748 x.fuzz, x.resolution);
2749 info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
2750 y.fuzz, y.resolution);
2751 }
2752 info->setButtonUnderPad(mParameters.hasButtonUnderPad);
2753 }
2754}
2755
2756void TouchInputMapper::dump(String8& dump) {
2757 dump.append(INDENT2 "Touch Input Mapper:\n");
2758 dumpParameters(dump);
2759 dumpVirtualKeys(dump);
2760 dumpRawPointerAxes(dump);
2761 dumpCalibration(dump);
Jason Gereckeaf126fb2012-05-10 14:22:47 -07002762 dumpAffineTransformation(dump);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002763 dumpSurface(dump);
2764
2765 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
2766 dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
2767 dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
2768 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
2769 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
2770 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
2771 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
2772 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
2773 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
2774 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
2775 dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
2776 dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
2777 dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
2778 dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
2779 dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
2780 dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
2781 dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
2782
Michael Wright842500e2015-03-13 17:32:02 -07002783 dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002784
2785 dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07002786 mLastRawState.rawPointerData.pointerCount);
2787 for (uint32_t i = 0; i < mLastRawState.rawPointerData.pointerCount; i++) {
2788 const RawPointerData::Pointer& pointer = mLastRawState.rawPointerData.pointers[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08002789 dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
2790 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
2791 "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
2792 "toolType=%d, isHovering=%s\n", i,
2793 pointer.id, pointer.x, pointer.y, pointer.pressure,
2794 pointer.touchMajor, pointer.touchMinor,
2795 pointer.toolMajor, pointer.toolMinor,
2796 pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
2797 pointer.toolType, toString(pointer.isHovering));
2798 }
2799
2800 dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
Michael Wright842500e2015-03-13 17:32:02 -07002801 mLastCookedState.cookedPointerData.pointerCount);
2802 for (uint32_t i = 0; i < mLastCookedState.cookedPointerData.pointerCount; i++) {
2803 const PointerProperties& pointerProperties =
2804 mLastCookedState.cookedPointerData.pointerProperties[i];
2805 const PointerCoords& pointerCoords = mLastCookedState.cookedPointerData.pointerCoords[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08002806 dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
2807 "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
2808 "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
2809 "toolType=%d, isHovering=%s\n", i,
2810 pointerProperties.id,
2811 pointerCoords.getX(),
2812 pointerCoords.getY(),
2813 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
2814 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
2815 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
2816 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
2817 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
2818 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
2819 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
2820 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
2821 pointerProperties.toolType,
Michael Wright842500e2015-03-13 17:32:02 -07002822 toString(mLastCookedState.cookedPointerData.isHovering(i)));
Michael Wrightd02c5b62014-02-10 15:10:22 -08002823 }
2824
Michael Wright842500e2015-03-13 17:32:02 -07002825 dump.append(INDENT3 "Stylus Fusion:\n");
2826 dump.appendFormat(INDENT4 "ExternalStylusConnected: %s\n",
2827 toString(mExternalStylusConnected));
2828 dump.appendFormat(INDENT4 "External Stylus ID: %" PRId64 "\n", mExternalStylusId);
2829 dump.appendFormat(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
2830 mExternalStylusDataTimeout);
2831 dump.append(INDENT3 "External Stylus State:\n");
2832 dumpStylusState(dump, mExternalStylusState);
2833
Michael Wrightd02c5b62014-02-10 15:10:22 -08002834 if (mDeviceMode == DEVICE_MODE_POINTER) {
2835 dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
2836 dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
2837 mPointerXMovementScale);
2838 dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
2839 mPointerYMovementScale);
2840 dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
2841 mPointerXZoomScale);
2842 dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
2843 mPointerYZoomScale);
2844 dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
2845 mPointerGestureMaxSwipeWidth);
2846 }
2847}
2848
2849void TouchInputMapper::configure(nsecs_t when,
2850 const InputReaderConfiguration* config, uint32_t changes) {
2851 InputMapper::configure(when, config, changes);
2852
2853 mConfig = *config;
2854
2855 if (!changes) { // first time only
2856 // Configure basic parameters.
2857 configureParameters();
2858
2859 // Configure common accumulators.
2860 mCursorScrollAccumulator.configure(getDevice());
2861 mTouchButtonAccumulator.configure(getDevice());
2862
2863 // Configure absolute axis information.
2864 configureRawPointerAxes();
2865
2866 // Prepare input device calibration.
2867 parseCalibration();
2868 resolveCalibration();
2869 }
2870
Michael Wright842500e2015-03-13 17:32:02 -07002871 if (!changes || (changes & InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION)) {
Jason Gerecke12d6baa2014-01-27 18:34:20 -08002872 // Update location calibration to reflect current settings
2873 updateAffineTransformation();
2874 }
2875
Michael Wrightd02c5b62014-02-10 15:10:22 -08002876 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2877 // Update pointer speed.
2878 mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
2879 mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
2880 mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
2881 }
2882
2883 bool resetNeeded = false;
2884 if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
2885 | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
Michael Wright842500e2015-03-13 17:32:02 -07002886 | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
2887 | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08002888 // Configure device sources, surface dimensions, orientation and
2889 // scaling factors.
2890 configureSurface(when, &resetNeeded);
2891 }
2892
2893 if (changes && resetNeeded) {
2894 // Send reset, unless this is the first time the device has been configured,
2895 // in which case the reader will call reset itself after all mappers are ready.
2896 getDevice()->notifyReset(when);
2897 }
2898}
2899
Michael Wright842500e2015-03-13 17:32:02 -07002900void TouchInputMapper::resolveExternalStylusPresence() {
2901 Vector<InputDeviceInfo> devices;
2902 mContext->getExternalStylusDevices(devices);
2903 mExternalStylusConnected = !devices.isEmpty();
2904
2905 if (!mExternalStylusConnected) {
2906 resetExternalStylus();
2907 }
2908}
2909
Michael Wrightd02c5b62014-02-10 15:10:22 -08002910void TouchInputMapper::configureParameters() {
2911 // Use the pointer presentation mode for devices that do not support distinct
2912 // multitouch. The spot-based presentation relies on being able to accurately
2913 // locate two or more fingers on the touch pad.
2914 mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
2915 ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
2916
2917 String8 gestureModeString;
2918 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
2919 gestureModeString)) {
2920 if (gestureModeString == "pointer") {
2921 mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
2922 } else if (gestureModeString == "spots") {
2923 mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
2924 } else if (gestureModeString != "default") {
2925 ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
2926 }
2927 }
2928
2929 if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
2930 // The device is a touch screen.
2931 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2932 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
2933 // The device is a pointing device like a track pad.
2934 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2935 } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
2936 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
2937 // The device is a cursor device with a touch pad attached.
2938 // By default don't use the touch pad to move the pointer.
2939 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2940 } else {
2941 // The device is a touch pad of unknown purpose.
2942 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2943 }
2944
2945 mParameters.hasButtonUnderPad=
2946 getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
2947
2948 String8 deviceTypeString;
2949 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
2950 deviceTypeString)) {
2951 if (deviceTypeString == "touchScreen") {
2952 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2953 } else if (deviceTypeString == "touchPad") {
2954 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2955 } else if (deviceTypeString == "touchNavigation") {
2956 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
2957 } else if (deviceTypeString == "pointer") {
2958 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2959 } else if (deviceTypeString != "default") {
2960 ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
2961 }
2962 }
2963
2964 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2965 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
2966 mParameters.orientationAware);
2967
2968 mParameters.hasAssociatedDisplay = false;
2969 mParameters.associatedDisplayIsExternal = false;
2970 if (mParameters.orientationAware
2971 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2972 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2973 mParameters.hasAssociatedDisplay = true;
2974 mParameters.associatedDisplayIsExternal =
2975 mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2976 && getDevice()->isExternal();
2977 }
Jeff Brownc5e24422014-02-26 18:48:51 -08002978
2979 // Initial downs on external touch devices should wake the device.
2980 // Normally we don't do this for internal touch screens to prevent them from waking
2981 // up in your pocket but you can enable it using the input device configuration.
2982 mParameters.wake = getDevice()->isExternal();
2983 getDevice()->getConfiguration().tryGetProperty(String8("touch.wake"),
2984 mParameters.wake);
Michael Wrightd02c5b62014-02-10 15:10:22 -08002985}
2986
2987void TouchInputMapper::dumpParameters(String8& dump) {
2988 dump.append(INDENT3 "Parameters:\n");
2989
2990 switch (mParameters.gestureMode) {
2991 case Parameters::GESTURE_MODE_POINTER:
2992 dump.append(INDENT4 "GestureMode: pointer\n");
2993 break;
2994 case Parameters::GESTURE_MODE_SPOTS:
2995 dump.append(INDENT4 "GestureMode: spots\n");
2996 break;
2997 default:
2998 assert(false);
2999 }
3000
3001 switch (mParameters.deviceType) {
3002 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
3003 dump.append(INDENT4 "DeviceType: touchScreen\n");
3004 break;
3005 case Parameters::DEVICE_TYPE_TOUCH_PAD:
3006 dump.append(INDENT4 "DeviceType: touchPad\n");
3007 break;
3008 case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
3009 dump.append(INDENT4 "DeviceType: touchNavigation\n");
3010 break;
3011 case Parameters::DEVICE_TYPE_POINTER:
3012 dump.append(INDENT4 "DeviceType: pointer\n");
3013 break;
3014 default:
3015 ALOG_ASSERT(false);
3016 }
3017
3018 dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
3019 toString(mParameters.hasAssociatedDisplay),
3020 toString(mParameters.associatedDisplayIsExternal));
3021 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
3022 toString(mParameters.orientationAware));
3023}
3024
3025void TouchInputMapper::configureRawPointerAxes() {
3026 mRawPointerAxes.clear();
3027}
3028
3029void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
3030 dump.append(INDENT3 "Raw Touch Axes:\n");
3031 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
3032 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
3033 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
3034 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
3035 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
3036 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
3037 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
3038 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
3039 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
3040 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
3041 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
3042 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
3043 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
3044}
3045
Michael Wright842500e2015-03-13 17:32:02 -07003046bool TouchInputMapper::hasExternalStylus() const {
3047 return mExternalStylusConnected;
3048}
3049
Michael Wrightd02c5b62014-02-10 15:10:22 -08003050void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
3051 int32_t oldDeviceMode = mDeviceMode;
3052
Michael Wright842500e2015-03-13 17:32:02 -07003053 resolveExternalStylusPresence();
3054
Michael Wrightd02c5b62014-02-10 15:10:22 -08003055 // Determine device mode.
3056 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
3057 && mConfig.pointerGesturesEnabled) {
3058 mSource = AINPUT_SOURCE_MOUSE;
3059 mDeviceMode = DEVICE_MODE_POINTER;
3060 if (hasStylus()) {
3061 mSource |= AINPUT_SOURCE_STYLUS;
3062 }
3063 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
3064 && mParameters.hasAssociatedDisplay) {
3065 mSource = AINPUT_SOURCE_TOUCHSCREEN;
3066 mDeviceMode = DEVICE_MODE_DIRECT;
Michael Wright842500e2015-03-13 17:32:02 -07003067 if (hasStylus() || hasExternalStylus()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003068 mSource |= AINPUT_SOURCE_STYLUS;
3069 }
3070 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
3071 mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
3072 mDeviceMode = DEVICE_MODE_NAVIGATION;
3073 } else {
3074 mSource = AINPUT_SOURCE_TOUCHPAD;
3075 mDeviceMode = DEVICE_MODE_UNSCALED;
3076 }
3077
3078 // Ensure we have valid X and Y axes.
3079 if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
3080 ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
3081 "The device will be inoperable.", getDeviceName().string());
3082 mDeviceMode = DEVICE_MODE_DISABLED;
3083 return;
3084 }
3085
3086 // Raw width and height in the natural orientation.
3087 int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
3088 int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
3089
3090 // Get associated display dimensions.
3091 DisplayViewport newViewport;
3092 if (mParameters.hasAssociatedDisplay) {
3093 if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
3094 ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
3095 "display. The device will be inoperable until the display size "
3096 "becomes available.",
3097 getDeviceName().string());
3098 mDeviceMode = DEVICE_MODE_DISABLED;
3099 return;
3100 }
3101 } else {
3102 newViewport.setNonDisplayViewport(rawWidth, rawHeight);
3103 }
3104 bool viewportChanged = mViewport != newViewport;
3105 if (viewportChanged) {
3106 mViewport = newViewport;
3107
3108 if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
3109 // Convert rotated viewport to natural surface coordinates.
3110 int32_t naturalLogicalWidth, naturalLogicalHeight;
3111 int32_t naturalPhysicalWidth, naturalPhysicalHeight;
3112 int32_t naturalPhysicalLeft, naturalPhysicalTop;
3113 int32_t naturalDeviceWidth, naturalDeviceHeight;
3114 switch (mViewport.orientation) {
3115 case DISPLAY_ORIENTATION_90:
3116 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3117 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3118 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3119 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3120 naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
3121 naturalPhysicalTop = mViewport.physicalLeft;
3122 naturalDeviceWidth = mViewport.deviceHeight;
3123 naturalDeviceHeight = mViewport.deviceWidth;
3124 break;
3125 case DISPLAY_ORIENTATION_180:
3126 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3127 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3128 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3129 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3130 naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
3131 naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
3132 naturalDeviceWidth = mViewport.deviceWidth;
3133 naturalDeviceHeight = mViewport.deviceHeight;
3134 break;
3135 case DISPLAY_ORIENTATION_270:
3136 naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
3137 naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
3138 naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
3139 naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
3140 naturalPhysicalLeft = mViewport.physicalTop;
3141 naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
3142 naturalDeviceWidth = mViewport.deviceHeight;
3143 naturalDeviceHeight = mViewport.deviceWidth;
3144 break;
3145 case DISPLAY_ORIENTATION_0:
3146 default:
3147 naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
3148 naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
3149 naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
3150 naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
3151 naturalPhysicalLeft = mViewport.physicalLeft;
3152 naturalPhysicalTop = mViewport.physicalTop;
3153 naturalDeviceWidth = mViewport.deviceWidth;
3154 naturalDeviceHeight = mViewport.deviceHeight;
3155 break;
3156 }
3157
3158 mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
3159 mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
3160 mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
3161 mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
3162
3163 mSurfaceOrientation = mParameters.orientationAware ?
3164 mViewport.orientation : DISPLAY_ORIENTATION_0;
3165 } else {
3166 mSurfaceWidth = rawWidth;
3167 mSurfaceHeight = rawHeight;
3168 mSurfaceLeft = 0;
3169 mSurfaceTop = 0;
3170 mSurfaceOrientation = DISPLAY_ORIENTATION_0;
3171 }
3172 }
3173
3174 // If moving between pointer modes, need to reset some state.
3175 bool deviceModeChanged = mDeviceMode != oldDeviceMode;
3176 if (deviceModeChanged) {
3177 mOrientedRanges.clear();
3178 }
3179
3180 // Create pointer controller if needed.
3181 if (mDeviceMode == DEVICE_MODE_POINTER ||
3182 (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
3183 if (mPointerController == NULL) {
3184 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
3185 }
3186 } else {
3187 mPointerController.clear();
3188 }
3189
3190 if (viewportChanged || deviceModeChanged) {
3191 ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
3192 "display id %d",
3193 getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
3194 mSurfaceOrientation, mDeviceMode, mViewport.displayId);
3195
3196 // Configure X and Y factors.
3197 mXScale = float(mSurfaceWidth) / rawWidth;
3198 mYScale = float(mSurfaceHeight) / rawHeight;
3199 mXTranslate = -mSurfaceLeft;
3200 mYTranslate = -mSurfaceTop;
3201 mXPrecision = 1.0f / mXScale;
3202 mYPrecision = 1.0f / mYScale;
3203
3204 mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
3205 mOrientedRanges.x.source = mSource;
3206 mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
3207 mOrientedRanges.y.source = mSource;
3208
3209 configureVirtualKeys();
3210
3211 // Scale factor for terms that are not oriented in a particular axis.
3212 // If the pixels are square then xScale == yScale otherwise we fake it
3213 // by choosing an average.
3214 mGeometricScale = avg(mXScale, mYScale);
3215
3216 // Size of diagonal axis.
3217 float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
3218
3219 // Size factors.
3220 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
3221 if (mRawPointerAxes.touchMajor.valid
3222 && mRawPointerAxes.touchMajor.maxValue != 0) {
3223 mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
3224 } else if (mRawPointerAxes.toolMajor.valid
3225 && mRawPointerAxes.toolMajor.maxValue != 0) {
3226 mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
3227 } else {
3228 mSizeScale = 0.0f;
3229 }
3230
3231 mOrientedRanges.haveTouchSize = true;
3232 mOrientedRanges.haveToolSize = true;
3233 mOrientedRanges.haveSize = true;
3234
3235 mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
3236 mOrientedRanges.touchMajor.source = mSource;
3237 mOrientedRanges.touchMajor.min = 0;
3238 mOrientedRanges.touchMajor.max = diagonalSize;
3239 mOrientedRanges.touchMajor.flat = 0;
3240 mOrientedRanges.touchMajor.fuzz = 0;
3241 mOrientedRanges.touchMajor.resolution = 0;
3242
3243 mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
3244 mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
3245
3246 mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
3247 mOrientedRanges.toolMajor.source = mSource;
3248 mOrientedRanges.toolMajor.min = 0;
3249 mOrientedRanges.toolMajor.max = diagonalSize;
3250 mOrientedRanges.toolMajor.flat = 0;
3251 mOrientedRanges.toolMajor.fuzz = 0;
3252 mOrientedRanges.toolMajor.resolution = 0;
3253
3254 mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
3255 mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
3256
3257 mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
3258 mOrientedRanges.size.source = mSource;
3259 mOrientedRanges.size.min = 0;
3260 mOrientedRanges.size.max = 1.0;
3261 mOrientedRanges.size.flat = 0;
3262 mOrientedRanges.size.fuzz = 0;
3263 mOrientedRanges.size.resolution = 0;
3264 } else {
3265 mSizeScale = 0.0f;
3266 }
3267
3268 // Pressure factors.
3269 mPressureScale = 0;
3270 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
3271 || mCalibration.pressureCalibration
3272 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
3273 if (mCalibration.havePressureScale) {
3274 mPressureScale = mCalibration.pressureScale;
3275 } else if (mRawPointerAxes.pressure.valid
3276 && mRawPointerAxes.pressure.maxValue != 0) {
3277 mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
3278 }
3279 }
3280
3281 mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
3282 mOrientedRanges.pressure.source = mSource;
3283 mOrientedRanges.pressure.min = 0;
3284 mOrientedRanges.pressure.max = 1.0;
3285 mOrientedRanges.pressure.flat = 0;
3286 mOrientedRanges.pressure.fuzz = 0;
3287 mOrientedRanges.pressure.resolution = 0;
3288
3289 // Tilt
3290 mTiltXCenter = 0;
3291 mTiltXScale = 0;
3292 mTiltYCenter = 0;
3293 mTiltYScale = 0;
3294 mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
3295 if (mHaveTilt) {
3296 mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
3297 mRawPointerAxes.tiltX.maxValue);
3298 mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
3299 mRawPointerAxes.tiltY.maxValue);
3300 mTiltXScale = M_PI / 180;
3301 mTiltYScale = M_PI / 180;
3302
3303 mOrientedRanges.haveTilt = true;
3304
3305 mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
3306 mOrientedRanges.tilt.source = mSource;
3307 mOrientedRanges.tilt.min = 0;
3308 mOrientedRanges.tilt.max = M_PI_2;
3309 mOrientedRanges.tilt.flat = 0;
3310 mOrientedRanges.tilt.fuzz = 0;
3311 mOrientedRanges.tilt.resolution = 0;
3312 }
3313
3314 // Orientation
3315 mOrientationScale = 0;
3316 if (mHaveTilt) {
3317 mOrientedRanges.haveOrientation = true;
3318
3319 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3320 mOrientedRanges.orientation.source = mSource;
3321 mOrientedRanges.orientation.min = -M_PI;
3322 mOrientedRanges.orientation.max = M_PI;
3323 mOrientedRanges.orientation.flat = 0;
3324 mOrientedRanges.orientation.fuzz = 0;
3325 mOrientedRanges.orientation.resolution = 0;
3326 } else if (mCalibration.orientationCalibration !=
3327 Calibration::ORIENTATION_CALIBRATION_NONE) {
3328 if (mCalibration.orientationCalibration
3329 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
3330 if (mRawPointerAxes.orientation.valid) {
3331 if (mRawPointerAxes.orientation.maxValue > 0) {
3332 mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
3333 } else if (mRawPointerAxes.orientation.minValue < 0) {
3334 mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
3335 } else {
3336 mOrientationScale = 0;
3337 }
3338 }
3339 }
3340
3341 mOrientedRanges.haveOrientation = true;
3342
3343 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
3344 mOrientedRanges.orientation.source = mSource;
3345 mOrientedRanges.orientation.min = -M_PI_2;
3346 mOrientedRanges.orientation.max = M_PI_2;
3347 mOrientedRanges.orientation.flat = 0;
3348 mOrientedRanges.orientation.fuzz = 0;
3349 mOrientedRanges.orientation.resolution = 0;
3350 }
3351
3352 // Distance
3353 mDistanceScale = 0;
3354 if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
3355 if (mCalibration.distanceCalibration
3356 == Calibration::DISTANCE_CALIBRATION_SCALED) {
3357 if (mCalibration.haveDistanceScale) {
3358 mDistanceScale = mCalibration.distanceScale;
3359 } else {
3360 mDistanceScale = 1.0f;
3361 }
3362 }
3363
3364 mOrientedRanges.haveDistance = true;
3365
3366 mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
3367 mOrientedRanges.distance.source = mSource;
3368 mOrientedRanges.distance.min =
3369 mRawPointerAxes.distance.minValue * mDistanceScale;
3370 mOrientedRanges.distance.max =
3371 mRawPointerAxes.distance.maxValue * mDistanceScale;
3372 mOrientedRanges.distance.flat = 0;
3373 mOrientedRanges.distance.fuzz =
3374 mRawPointerAxes.distance.fuzz * mDistanceScale;
3375 mOrientedRanges.distance.resolution = 0;
3376 }
3377
3378 // Compute oriented precision, scales and ranges.
3379 // Note that the maximum value reported is an inclusive maximum value so it is one
3380 // unit less than the total width or height of surface.
3381 switch (mSurfaceOrientation) {
3382 case DISPLAY_ORIENTATION_90:
3383 case DISPLAY_ORIENTATION_270:
3384 mOrientedXPrecision = mYPrecision;
3385 mOrientedYPrecision = mXPrecision;
3386
3387 mOrientedRanges.x.min = mYTranslate;
3388 mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
3389 mOrientedRanges.x.flat = 0;
3390 mOrientedRanges.x.fuzz = 0;
3391 mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
3392
3393 mOrientedRanges.y.min = mXTranslate;
3394 mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
3395 mOrientedRanges.y.flat = 0;
3396 mOrientedRanges.y.fuzz = 0;
3397 mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
3398 break;
3399
3400 default:
3401 mOrientedXPrecision = mXPrecision;
3402 mOrientedYPrecision = mYPrecision;
3403
3404 mOrientedRanges.x.min = mXTranslate;
3405 mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
3406 mOrientedRanges.x.flat = 0;
3407 mOrientedRanges.x.fuzz = 0;
3408 mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
3409
3410 mOrientedRanges.y.min = mYTranslate;
3411 mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
3412 mOrientedRanges.y.flat = 0;
3413 mOrientedRanges.y.fuzz = 0;
3414 mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
3415 break;
3416 }
3417
Jason Gerecke71b16e82014-03-10 09:47:59 -07003418 // Location
3419 updateAffineTransformation();
3420
Michael Wrightd02c5b62014-02-10 15:10:22 -08003421 if (mDeviceMode == DEVICE_MODE_POINTER) {
3422 // Compute pointer gesture detection parameters.
3423 float rawDiagonal = hypotf(rawWidth, rawHeight);
3424 float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
3425
3426 // Scale movements such that one whole swipe of the touch pad covers a
3427 // given area relative to the diagonal size of the display when no acceleration
3428 // is applied.
3429 // Assume that the touch pad has a square aspect ratio such that movements in
3430 // X and Y of the same number of raw units cover the same physical distance.
3431 mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
3432 * displayDiagonal / rawDiagonal;
3433 mPointerYMovementScale = mPointerXMovementScale;
3434
3435 // Scale zooms to cover a smaller range of the display than movements do.
3436 // This value determines the area around the pointer that is affected by freeform
3437 // pointer gestures.
3438 mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
3439 * displayDiagonal / rawDiagonal;
3440 mPointerYZoomScale = mPointerXZoomScale;
3441
3442 // Max width between pointers to detect a swipe gesture is more than some fraction
3443 // of the diagonal axis of the touch pad. Touches that are wider than this are
3444 // translated into freeform gestures.
3445 mPointerGestureMaxSwipeWidth =
3446 mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
3447
3448 // Abort current pointer usages because the state has changed.
3449 abortPointerUsage(when, 0 /*policyFlags*/);
3450 }
3451
3452 // Inform the dispatcher about the changes.
3453 *outResetNeeded = true;
3454 bumpGeneration();
3455 }
3456}
3457
3458void TouchInputMapper::dumpSurface(String8& dump) {
3459 dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
3460 "logicalFrame=[%d, %d, %d, %d], "
3461 "physicalFrame=[%d, %d, %d, %d], "
3462 "deviceSize=[%d, %d]\n",
3463 mViewport.displayId, mViewport.orientation,
3464 mViewport.logicalLeft, mViewport.logicalTop,
3465 mViewport.logicalRight, mViewport.logicalBottom,
3466 mViewport.physicalLeft, mViewport.physicalTop,
3467 mViewport.physicalRight, mViewport.physicalBottom,
3468 mViewport.deviceWidth, mViewport.deviceHeight);
3469
3470 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
3471 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
3472 dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
3473 dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
3474 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
3475}
3476
3477void TouchInputMapper::configureVirtualKeys() {
3478 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
3479 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
3480
3481 mVirtualKeys.clear();
3482
3483 if (virtualKeyDefinitions.size() == 0) {
3484 return;
3485 }
3486
3487 mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
3488
3489 int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
3490 int32_t touchScreenTop = mRawPointerAxes.y.minValue;
3491 int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
3492 int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
3493
3494 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
3495 const VirtualKeyDefinition& virtualKeyDefinition =
3496 virtualKeyDefinitions[i];
3497
3498 mVirtualKeys.add();
3499 VirtualKey& virtualKey = mVirtualKeys.editTop();
3500
3501 virtualKey.scanCode = virtualKeyDefinition.scanCode;
3502 int32_t keyCode;
3503 uint32_t flags;
3504 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
3505 ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
3506 virtualKey.scanCode);
3507 mVirtualKeys.pop(); // drop the key
3508 continue;
3509 }
3510
3511 virtualKey.keyCode = keyCode;
3512 virtualKey.flags = flags;
3513
3514 // convert the key definition's display coordinates into touch coordinates for a hit box
3515 int32_t halfWidth = virtualKeyDefinition.width / 2;
3516 int32_t halfHeight = virtualKeyDefinition.height / 2;
3517
3518 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
3519 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3520 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
3521 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
3522 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
3523 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3524 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
3525 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
3526 }
3527}
3528
3529void TouchInputMapper::dumpVirtualKeys(String8& dump) {
3530 if (!mVirtualKeys.isEmpty()) {
3531 dump.append(INDENT3 "Virtual Keys:\n");
3532
3533 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
3534 const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
Mark Salyzyn41d2f802014-03-18 10:59:23 -07003535 dump.appendFormat(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
Michael Wrightd02c5b62014-02-10 15:10:22 -08003536 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
3537 i, virtualKey.scanCode, virtualKey.keyCode,
3538 virtualKey.hitLeft, virtualKey.hitRight,
3539 virtualKey.hitTop, virtualKey.hitBottom);
3540 }
3541 }
3542}
3543
3544void TouchInputMapper::parseCalibration() {
3545 const PropertyMap& in = getDevice()->getConfiguration();
3546 Calibration& out = mCalibration;
3547
3548 // Size
3549 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
3550 String8 sizeCalibrationString;
3551 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
3552 if (sizeCalibrationString == "none") {
3553 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3554 } else if (sizeCalibrationString == "geometric") {
3555 out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3556 } else if (sizeCalibrationString == "diameter") {
3557 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
3558 } else if (sizeCalibrationString == "box") {
3559 out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
3560 } else if (sizeCalibrationString == "area") {
3561 out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
3562 } else if (sizeCalibrationString != "default") {
3563 ALOGW("Invalid value for touch.size.calibration: '%s'",
3564 sizeCalibrationString.string());
3565 }
3566 }
3567
3568 out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
3569 out.sizeScale);
3570 out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
3571 out.sizeBias);
3572 out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
3573 out.sizeIsSummed);
3574
3575 // Pressure
3576 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
3577 String8 pressureCalibrationString;
3578 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
3579 if (pressureCalibrationString == "none") {
3580 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3581 } else if (pressureCalibrationString == "physical") {
3582 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3583 } else if (pressureCalibrationString == "amplitude") {
3584 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
3585 } else if (pressureCalibrationString != "default") {
3586 ALOGW("Invalid value for touch.pressure.calibration: '%s'",
3587 pressureCalibrationString.string());
3588 }
3589 }
3590
3591 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
3592 out.pressureScale);
3593
3594 // Orientation
3595 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
3596 String8 orientationCalibrationString;
3597 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
3598 if (orientationCalibrationString == "none") {
3599 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3600 } else if (orientationCalibrationString == "interpolated") {
3601 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3602 } else if (orientationCalibrationString == "vector") {
3603 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
3604 } else if (orientationCalibrationString != "default") {
3605 ALOGW("Invalid value for touch.orientation.calibration: '%s'",
3606 orientationCalibrationString.string());
3607 }
3608 }
3609
3610 // Distance
3611 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
3612 String8 distanceCalibrationString;
3613 if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
3614 if (distanceCalibrationString == "none") {
3615 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3616 } else if (distanceCalibrationString == "scaled") {
3617 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3618 } else if (distanceCalibrationString != "default") {
3619 ALOGW("Invalid value for touch.distance.calibration: '%s'",
3620 distanceCalibrationString.string());
3621 }
3622 }
3623
3624 out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
3625 out.distanceScale);
3626
3627 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
3628 String8 coverageCalibrationString;
3629 if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
3630 if (coverageCalibrationString == "none") {
3631 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
3632 } else if (coverageCalibrationString == "box") {
3633 out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
3634 } else if (coverageCalibrationString != "default") {
3635 ALOGW("Invalid value for touch.coverage.calibration: '%s'",
3636 coverageCalibrationString.string());
3637 }
3638 }
3639}
3640
3641void TouchInputMapper::resolveCalibration() {
3642 // Size
3643 if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
3644 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
3645 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3646 }
3647 } else {
3648 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3649 }
3650
3651 // Pressure
3652 if (mRawPointerAxes.pressure.valid) {
3653 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
3654 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3655 }
3656 } else {
3657 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3658 }
3659
3660 // Orientation
3661 if (mRawPointerAxes.orientation.valid) {
3662 if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
3663 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3664 }
3665 } else {
3666 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3667 }
3668
3669 // Distance
3670 if (mRawPointerAxes.distance.valid) {
3671 if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
3672 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3673 }
3674 } else {
3675 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3676 }
3677
3678 // Coverage
3679 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
3680 mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
3681 }
3682}
3683
3684void TouchInputMapper::dumpCalibration(String8& dump) {
3685 dump.append(INDENT3 "Calibration:\n");
3686
3687 // Size
3688 switch (mCalibration.sizeCalibration) {
3689 case Calibration::SIZE_CALIBRATION_NONE:
3690 dump.append(INDENT4 "touch.size.calibration: none\n");
3691 break;
3692 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
3693 dump.append(INDENT4 "touch.size.calibration: geometric\n");
3694 break;
3695 case Calibration::SIZE_CALIBRATION_DIAMETER:
3696 dump.append(INDENT4 "touch.size.calibration: diameter\n");
3697 break;
3698 case Calibration::SIZE_CALIBRATION_BOX:
3699 dump.append(INDENT4 "touch.size.calibration: box\n");
3700 break;
3701 case Calibration::SIZE_CALIBRATION_AREA:
3702 dump.append(INDENT4 "touch.size.calibration: area\n");
3703 break;
3704 default:
3705 ALOG_ASSERT(false);
3706 }
3707
3708 if (mCalibration.haveSizeScale) {
3709 dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
3710 mCalibration.sizeScale);
3711 }
3712
3713 if (mCalibration.haveSizeBias) {
3714 dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
3715 mCalibration.sizeBias);
3716 }
3717
3718 if (mCalibration.haveSizeIsSummed) {
3719 dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
3720 toString(mCalibration.sizeIsSummed));
3721 }
3722
3723 // Pressure
3724 switch (mCalibration.pressureCalibration) {
3725 case Calibration::PRESSURE_CALIBRATION_NONE:
3726 dump.append(INDENT4 "touch.pressure.calibration: none\n");
3727 break;
3728 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3729 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
3730 break;
3731 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3732 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
3733 break;
3734 default:
3735 ALOG_ASSERT(false);
3736 }
3737
3738 if (mCalibration.havePressureScale) {
3739 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
3740 mCalibration.pressureScale);
3741 }
3742
3743 // Orientation
3744 switch (mCalibration.orientationCalibration) {
3745 case Calibration::ORIENTATION_CALIBRATION_NONE:
3746 dump.append(INDENT4 "touch.orientation.calibration: none\n");
3747 break;
3748 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3749 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
3750 break;
3751 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
3752 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
3753 break;
3754 default:
3755 ALOG_ASSERT(false);
3756 }
3757
3758 // Distance
3759 switch (mCalibration.distanceCalibration) {
3760 case Calibration::DISTANCE_CALIBRATION_NONE:
3761 dump.append(INDENT4 "touch.distance.calibration: none\n");
3762 break;
3763 case Calibration::DISTANCE_CALIBRATION_SCALED:
3764 dump.append(INDENT4 "touch.distance.calibration: scaled\n");
3765 break;
3766 default:
3767 ALOG_ASSERT(false);
3768 }
3769
3770 if (mCalibration.haveDistanceScale) {
3771 dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
3772 mCalibration.distanceScale);
3773 }
3774
3775 switch (mCalibration.coverageCalibration) {
3776 case Calibration::COVERAGE_CALIBRATION_NONE:
3777 dump.append(INDENT4 "touch.coverage.calibration: none\n");
3778 break;
3779 case Calibration::COVERAGE_CALIBRATION_BOX:
3780 dump.append(INDENT4 "touch.coverage.calibration: box\n");
3781 break;
3782 default:
3783 ALOG_ASSERT(false);
3784 }
3785}
3786
Jason Gereckeaf126fb2012-05-10 14:22:47 -07003787void TouchInputMapper::dumpAffineTransformation(String8& dump) {
3788 dump.append(INDENT3 "Affine Transformation:\n");
3789
3790 dump.appendFormat(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
3791 dump.appendFormat(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
3792 dump.appendFormat(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
3793 dump.appendFormat(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
3794 dump.appendFormat(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
3795 dump.appendFormat(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
3796}
3797
Jason Gerecke12d6baa2014-01-27 18:34:20 -08003798void TouchInputMapper::updateAffineTransformation() {
Jason Gerecke71b16e82014-03-10 09:47:59 -07003799 mAffineTransform = getPolicy()->getTouchAffineTransformation(mDevice->getDescriptor(),
3800 mSurfaceOrientation);
Jason Gerecke12d6baa2014-01-27 18:34:20 -08003801}
3802
Michael Wrightd02c5b62014-02-10 15:10:22 -08003803void TouchInputMapper::reset(nsecs_t when) {
3804 mCursorButtonAccumulator.reset(getDevice());
3805 mCursorScrollAccumulator.reset(getDevice());
3806 mTouchButtonAccumulator.reset(getDevice());
3807
3808 mPointerVelocityControl.reset();
3809 mWheelXVelocityControl.reset();
3810 mWheelYVelocityControl.reset();
3811
Michael Wright842500e2015-03-13 17:32:02 -07003812 mRawStatesPending.clear();
3813 mCurrentRawState.clear();
3814 mCurrentCookedState.clear();
3815 mLastRawState.clear();
3816 mLastCookedState.clear();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003817 mPointerUsage = POINTER_USAGE_NONE;
3818 mSentHoverEnter = false;
Michael Wright842500e2015-03-13 17:32:02 -07003819 mHavePointerIds = false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003820 mDownTime = 0;
3821
3822 mCurrentVirtualKey.down = false;
3823
3824 mPointerGesture.reset();
3825 mPointerSimple.reset();
Michael Wright842500e2015-03-13 17:32:02 -07003826 resetExternalStylus();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003827
3828 if (mPointerController != NULL) {
3829 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3830 mPointerController->clearSpots();
3831 }
3832
3833 InputMapper::reset(when);
3834}
3835
Michael Wright842500e2015-03-13 17:32:02 -07003836void TouchInputMapper::resetExternalStylus() {
3837 mExternalStylusState.clear();
3838 mExternalStylusId = -1;
3839 mExternalStylusDataTimeout = LLONG_MAX;
3840 mExternalStylusDataPending = false;
3841}
3842
Michael Wrightd02c5b62014-02-10 15:10:22 -08003843void TouchInputMapper::process(const RawEvent* rawEvent) {
3844 mCursorButtonAccumulator.process(rawEvent);
3845 mCursorScrollAccumulator.process(rawEvent);
3846 mTouchButtonAccumulator.process(rawEvent);
3847
3848 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
3849 sync(rawEvent->when);
3850 }
3851}
3852
3853void TouchInputMapper::sync(nsecs_t when) {
Michael Wright842500e2015-03-13 17:32:02 -07003854 const RawState* last = mRawStatesPending.isEmpty() ?
3855 &mCurrentRawState : &mRawStatesPending.top();
3856
3857 // Push a new state.
3858 mRawStatesPending.push();
3859 RawState* next = &mRawStatesPending.editTop();
3860 next->clear();
3861 next->when = when;
3862
Michael Wrightd02c5b62014-02-10 15:10:22 -08003863 // Sync button state.
Michael Wright842500e2015-03-13 17:32:02 -07003864 next->buttonState = mTouchButtonAccumulator.getButtonState()
Michael Wrightd02c5b62014-02-10 15:10:22 -08003865 | mCursorButtonAccumulator.getButtonState();
3866
Michael Wright842500e2015-03-13 17:32:02 -07003867 // Sync scroll
3868 next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
3869 next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
Michael Wrightd02c5b62014-02-10 15:10:22 -08003870 mCursorScrollAccumulator.finishSync();
3871
Michael Wright842500e2015-03-13 17:32:02 -07003872 // Sync touch
3873 syncTouch(when, next);
3874
3875 // Assign pointer ids.
3876 if (!mHavePointerIds) {
3877 assignPointerIds(last, next);
3878 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08003879
3880#if DEBUG_RAW_EVENTS
Michael Wright842500e2015-03-13 17:32:02 -07003881 ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
3882 "hovering ids 0x%08x -> 0x%08x",
3883 last->rawPointerData.pointerCount,
3884 next->rawPointerData.pointerCount,
3885 last->rawPointerData.touchingIdBits.value,
3886 next->rawPointerData.touchingIdBits.value,
3887 last->rawPointerData.hoveringIdBits.value,
3888 next->rawPointerData.hoveringIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08003889#endif
3890
Michael Wright842500e2015-03-13 17:32:02 -07003891 processRawTouches(false /*timeout*/);
3892}
Michael Wrightd02c5b62014-02-10 15:10:22 -08003893
Michael Wright842500e2015-03-13 17:32:02 -07003894void TouchInputMapper::processRawTouches(bool timeout) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08003895 if (mDeviceMode == DEVICE_MODE_DISABLED) {
3896 // Drop all input if the device is disabled.
Michael Wright842500e2015-03-13 17:32:02 -07003897 mCurrentRawState.clear();
3898 mRawStatesPending.clear();
3899 return;
Michael Wrightd02c5b62014-02-10 15:10:22 -08003900 }
3901
Michael Wright842500e2015-03-13 17:32:02 -07003902 // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
3903 // valid and must go through the full cook and dispatch cycle. This ensures that anything
3904 // touching the current state will only observe the events that have been dispatched to the
3905 // rest of the pipeline.
3906 const size_t N = mRawStatesPending.size();
3907 size_t count;
3908 for(count = 0; count < N; count++) {
3909 const RawState& next = mRawStatesPending[count];
3910
3911 // A failure to assign the stylus id means that we're waiting on stylus data
3912 // and so should defer the rest of the pipeline.
3913 if (assignExternalStylusId(next, timeout)) {
3914 break;
3915 }
3916
3917 // All ready to go.
3918 mExternalStylusDataPending = false;
3919 mCurrentRawState.copyFrom(next);
3920 cookAndDispatch(mCurrentRawState.when);
3921 }
3922 if (count != 0) {
3923 mRawStatesPending.removeItemsAt(0, count);
3924 }
3925
3926 // TODO: If we still have pending stylus data that hasn't been mapped to a touch yet
3927 // then set a timeout to synthesize a new touch event with the new data. Otherwise
3928 // we will lose button and pressure information while the touch is stationary.
3929 if (mExternalStylusDataPending) {
3930 ALOGD("STYLUS TODO: Wiggle wiggle wiggle.");
3931 }
3932}
3933
3934void TouchInputMapper::cookAndDispatch(nsecs_t when) {
3935 // Always start with a clean state.
3936 mCurrentCookedState.clear();
3937
3938 // Apply stylus buttons to current raw state.
3939 applyExternalStylusButtonState(when);
3940
3941 // Handle policy on initial down or hover events.
3942 bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
3943 && mCurrentRawState.rawPointerData.pointerCount != 0;
3944
3945 uint32_t policyFlags = 0;
3946 bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
3947 if (initialDown || buttonsPressed) {
3948 // If this is a touch screen, hide the pointer on an initial down.
3949 if (mDeviceMode == DEVICE_MODE_DIRECT) {
3950 getContext()->fadePointer();
3951 }
3952
3953 if (mParameters.wake) {
3954 policyFlags |= POLICY_FLAG_WAKE;
3955 }
3956 }
3957
3958 // Consume raw off-screen touches before cooking pointer data.
3959 // If touches are consumed, subsequent code will not receive any pointer data.
3960 if (consumeRawTouches(when, policyFlags)) {
3961 mCurrentRawState.rawPointerData.clear();
3962 }
3963
3964 // Cook pointer data. This call populates the mCurrentCookedState.cookedPointerData structure
3965 // with cooked pointer data that has the same ids and indices as the raw data.
3966 // The following code can use either the raw or cooked data, as needed.
3967 cookPointerData();
3968
3969 // Apply stylus pressure to current cooked state.
3970 applyExternalStylusTouchState(when);
3971
3972 // Synthesize key down from raw buttons if needed.
3973 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
3974 policyFlags, mLastRawState.buttonState, mCurrentRawState.buttonState);
3975
3976 // Dispatch the touches either directly or by translation through a pointer on screen.
3977 if (mDeviceMode == DEVICE_MODE_POINTER) {
3978 for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
3979 !idBits.isEmpty(); ) {
3980 uint32_t id = idBits.clearFirstMarkedBit();
3981 const RawPointerData::Pointer& pointer =
3982 mCurrentRawState.rawPointerData.pointerForId(id);
3983 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3984 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3985 mCurrentCookedState.stylusIdBits.markBit(id);
3986 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
3987 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
3988 mCurrentCookedState.fingerIdBits.markBit(id);
3989 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
3990 mCurrentCookedState.mouseIdBits.markBit(id);
3991 }
3992 }
3993 for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
3994 !idBits.isEmpty(); ) {
3995 uint32_t id = idBits.clearFirstMarkedBit();
3996 const RawPointerData::Pointer& pointer =
3997 mCurrentRawState.rawPointerData.pointerForId(id);
3998 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3999 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
4000 mCurrentCookedState.stylusIdBits.markBit(id);
4001 }
4002 }
4003
4004 // Stylus takes precedence over all tools, then mouse, then finger.
4005 PointerUsage pointerUsage = mPointerUsage;
4006 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
4007 mCurrentCookedState.mouseIdBits.clear();
4008 mCurrentCookedState.fingerIdBits.clear();
4009 pointerUsage = POINTER_USAGE_STYLUS;
4010 } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
4011 mCurrentCookedState.fingerIdBits.clear();
4012 pointerUsage = POINTER_USAGE_MOUSE;
4013 } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
4014 isPointerDown(mCurrentRawState.buttonState)) {
4015 pointerUsage = POINTER_USAGE_GESTURES;
4016 }
4017
4018 dispatchPointerUsage(when, policyFlags, pointerUsage);
4019 } else {
4020 if (mDeviceMode == DEVICE_MODE_DIRECT
4021 && mConfig.showTouches && mPointerController != NULL) {
4022 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
4023 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4024
4025 mPointerController->setButtonState(mCurrentRawState.buttonState);
4026 mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
4027 mCurrentCookedState.cookedPointerData.idToIndex,
4028 mCurrentCookedState.cookedPointerData.touchingIdBits);
4029 }
4030
4031 dispatchHoverExit(when, policyFlags);
4032 dispatchTouches(when, policyFlags);
4033 dispatchHoverEnterAndMove(when, policyFlags);
4034 }
4035
4036 // Synthesize key up from raw buttons if needed.
4037 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
4038 policyFlags, mLastRawState.buttonState, mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004039
4040 // Clear some transient state.
Michael Wright842500e2015-03-13 17:32:02 -07004041 mCurrentRawState.rawVScroll = 0;
4042 mCurrentRawState.rawHScroll = 0;
4043
4044 // Copy current touch to last touch in preparation for the next cycle.
4045 mLastRawState.copyFrom(mCurrentRawState);
4046 mLastCookedState.copyFrom(mCurrentCookedState);
4047}
4048
4049void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
4050 if (mDeviceMode == DEVICE_MODE_DIRECT && hasExternalStylus()) {
4051 mCurrentRawState.buttonState |= mExternalStylusState.buttons;
4052 }
4053}
4054
4055void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
4056 CookedPointerData& cpd = mCurrentCookedState.cookedPointerData;
4057 if (mExternalStylusId != -1 && cpd.isTouching(mExternalStylusId)) {
4058 if (mExternalStylusState.pressure != 0.0f) {
4059 PointerCoords& coords = cpd.editPointerCoordsWithId(mExternalStylusId);
4060 coords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mExternalStylusState.pressure);
4061 }
4062
4063 PointerProperties& properties = cpd.editPointerPropertiesWithId(mExternalStylusId);
4064 if (mExternalStylusState.toolType != AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
4065 properties.toolType = mExternalStylusState.toolType;
4066 }
4067 }
4068}
4069
4070bool TouchInputMapper::assignExternalStylusId(const RawState& state, bool timeout) {
4071 if (mDeviceMode != DEVICE_MODE_DIRECT || !hasExternalStylus()) {
4072 return false;
4073 }
4074
4075 const bool initialDown = mLastRawState.rawPointerData.pointerCount == 0
4076 && state.rawPointerData.pointerCount != 0;
4077 if (initialDown) {
4078 if (mExternalStylusState.pressure != 0.0f) {
4079#if DEBUG_STYLUS_FUSION
4080 ALOGD("Have both stylus and touch data, beginning fusion");
4081#endif
4082 mExternalStylusId = state.rawPointerData.touchingIdBits.firstMarkedBit();
4083 } else if (timeout) {
4084#if DEBUG_STYLUS_FUSION
4085 ALOGD("Timeout expired, assuming touch is not a stylus.");
4086#endif
4087 resetExternalStylus();
4088 } else {
4089 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
4090 if (mExternalStylusDataTimeout == LLONG_MAX) {
4091 mExternalStylusDataTimeout = now + EXTERNAL_STYLUS_DATA_TIMEOUT;
4092 }
4093#if DEBUG_STYLUS_FUSION
4094 ALOGD("No stylus data but stylus is connected, requesting timeout "
4095 "(%" PRId64 "ms)", mExternalStylusDataTimeout);
4096#endif
4097 getContext()->requestTimeoutAtTime(mExternalStylusDataTimeout);
4098 return true;
4099 }
4100 }
4101
4102 // Check if the stylus pointer has gone up.
4103 if (mExternalStylusId != -1 &&
4104 !state.rawPointerData.touchingIdBits.hasBit(mExternalStylusId)) {
4105#if DEBUG_STYLUS_FUSION
4106 ALOGD("Stylus pointer is going up");
4107#endif
4108 mExternalStylusId = -1;
4109 }
4110
4111 return false;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004112}
4113
4114void TouchInputMapper::timeoutExpired(nsecs_t when) {
4115 if (mDeviceMode == DEVICE_MODE_POINTER) {
4116 if (mPointerUsage == POINTER_USAGE_GESTURES) {
4117 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
4118 }
Michael Wright842500e2015-03-13 17:32:02 -07004119 } else if (mDeviceMode == DEVICE_MODE_DIRECT) {
4120 if (mExternalStylusDataTimeout < when) {
4121 mExternalStylusDataTimeout = LLONG_MAX;
4122 processRawTouches(true /*timeout*/);
4123 } else if (mExternalStylusDataTimeout != LLONG_MAX) {
4124 getContext()->requestTimeoutAtTime(mExternalStylusDataTimeout);
4125 }
4126 }
4127}
4128
4129void TouchInputMapper::updateExternalStylusState(const StylusState& state) {
Michael Wright4af18b92015-04-20 22:03:54 +01004130 mExternalStylusState.copyFrom(state);
Michael Wright842500e2015-03-13 17:32:02 -07004131 if (mExternalStylusId != -1 || mExternalStylusDataTimeout != LLONG_MAX) {
4132 // We're either in the middle of a fused stream of data or we're waiting on data before
4133 // dispatching the initial down, so go ahead and dispatch now that we have fresh stylus
4134 // data.
4135 mExternalStylusDataTimeout = LLONG_MAX;
4136 mExternalStylusDataPending = true;
Michael Wright842500e2015-03-13 17:32:02 -07004137 processRawTouches(false /*timeout*/);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004138 }
4139}
4140
4141bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
4142 // Check for release of a virtual key.
4143 if (mCurrentVirtualKey.down) {
Michael Wright842500e2015-03-13 17:32:02 -07004144 if (mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004145 // Pointer went up while virtual key was down.
4146 mCurrentVirtualKey.down = false;
4147 if (!mCurrentVirtualKey.ignored) {
4148#if DEBUG_VIRTUAL_KEYS
4149 ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
4150 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4151#endif
4152 dispatchVirtualKey(when, policyFlags,
4153 AKEY_EVENT_ACTION_UP,
4154 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4155 }
4156 return true;
4157 }
4158
Michael Wright842500e2015-03-13 17:32:02 -07004159 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
4160 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4161 const RawPointerData::Pointer& pointer =
4162 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004163 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4164 if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
4165 // Pointer is still within the space of the virtual key.
4166 return true;
4167 }
4168 }
4169
4170 // Pointer left virtual key area or another pointer also went down.
4171 // Send key cancellation but do not consume the touch yet.
4172 // This is useful when the user swipes through from the virtual key area
4173 // into the main display surface.
4174 mCurrentVirtualKey.down = false;
4175 if (!mCurrentVirtualKey.ignored) {
4176#if DEBUG_VIRTUAL_KEYS
4177 ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
4178 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
4179#endif
4180 dispatchVirtualKey(when, policyFlags,
4181 AKEY_EVENT_ACTION_UP,
4182 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
4183 | AKEY_EVENT_FLAG_CANCELED);
4184 }
4185 }
4186
Michael Wright842500e2015-03-13 17:32:02 -07004187 if (mLastRawState.rawPointerData.touchingIdBits.isEmpty()
4188 && !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004189 // Pointer just went down. Check for virtual key press or off-screen touches.
Michael Wright842500e2015-03-13 17:32:02 -07004190 uint32_t id = mCurrentRawState.rawPointerData.touchingIdBits.firstMarkedBit();
4191 const RawPointerData::Pointer& pointer = mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004192 if (!isPointInsideSurface(pointer.x, pointer.y)) {
4193 // If exactly one pointer went down, check for virtual key hit.
4194 // Otherwise we will drop the entire stroke.
Michael Wright842500e2015-03-13 17:32:02 -07004195 if (mCurrentRawState.rawPointerData.touchingIdBits.count() == 1) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004196 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
4197 if (virtualKey) {
4198 mCurrentVirtualKey.down = true;
4199 mCurrentVirtualKey.downTime = when;
4200 mCurrentVirtualKey.keyCode = virtualKey->keyCode;
4201 mCurrentVirtualKey.scanCode = virtualKey->scanCode;
4202 mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
4203 when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
4204
4205 if (!mCurrentVirtualKey.ignored) {
4206#if DEBUG_VIRTUAL_KEYS
4207 ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
4208 mCurrentVirtualKey.keyCode,
4209 mCurrentVirtualKey.scanCode);
4210#endif
4211 dispatchVirtualKey(when, policyFlags,
4212 AKEY_EVENT_ACTION_DOWN,
4213 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
4214 }
4215 }
4216 }
4217 return true;
4218 }
4219 }
4220
4221 // Disable all virtual key touches that happen within a short time interval of the
4222 // most recent touch within the screen area. The idea is to filter out stray
4223 // virtual key presses when interacting with the touch screen.
4224 //
4225 // Problems we're trying to solve:
4226 //
4227 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
4228 // virtual key area that is implemented by a separate touch panel and accidentally
4229 // triggers a virtual key.
4230 //
4231 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
4232 // area and accidentally triggers a virtual key. This often happens when virtual keys
4233 // are layed out below the screen near to where the on screen keyboard's space bar
4234 // is displayed.
Michael Wright842500e2015-03-13 17:32:02 -07004235 if (mConfig.virtualKeyQuietTime > 0 &&
4236 !mCurrentRawState.rawPointerData.touchingIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004237 mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
4238 }
4239 return false;
4240}
4241
4242void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
4243 int32_t keyEventAction, int32_t keyEventFlags) {
4244 int32_t keyCode = mCurrentVirtualKey.keyCode;
4245 int32_t scanCode = mCurrentVirtualKey.scanCode;
4246 nsecs_t downTime = mCurrentVirtualKey.downTime;
4247 int32_t metaState = mContext->getGlobalMetaState();
4248 policyFlags |= POLICY_FLAG_VIRTUAL;
4249
4250 NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
4251 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
4252 getListener()->notifyKey(&args);
4253}
4254
4255void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004256 BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
4257 BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004258 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright842500e2015-03-13 17:32:02 -07004259 int32_t buttonState = mCurrentRawState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004260
4261 if (currentIdBits == lastIdBits) {
4262 if (!currentIdBits.isEmpty()) {
4263 // No pointer id changes so this is a move event.
4264 // The listener takes care of batching moves so we don't have to deal with that here.
4265 dispatchMotion(when, policyFlags, mSource,
4266 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
4267 AMOTION_EVENT_EDGE_FLAG_NONE,
Michael Wright842500e2015-03-13 17:32:02 -07004268 mCurrentCookedState.cookedPointerData.pointerProperties,
4269 mCurrentCookedState.cookedPointerData.pointerCoords,
4270 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004271 currentIdBits, -1,
4272 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4273 }
4274 } else {
4275 // There may be pointers going up and pointers going down and pointers moving
4276 // all at the same time.
4277 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
4278 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
4279 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
4280 BitSet32 dispatchedIdBits(lastIdBits.value);
4281
4282 // Update last coordinates of pointers that have moved so that we observe the new
4283 // pointer positions at the same time as other pointers that have just gone up.
4284 bool moveNeeded = updateMovedPointers(
Michael Wright842500e2015-03-13 17:32:02 -07004285 mCurrentCookedState.cookedPointerData.pointerProperties,
4286 mCurrentCookedState.cookedPointerData.pointerCoords,
4287 mCurrentCookedState.cookedPointerData.idToIndex,
4288 mLastCookedState.cookedPointerData.pointerProperties,
4289 mLastCookedState.cookedPointerData.pointerCoords,
4290 mLastCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004291 moveIdBits);
Michael Wright842500e2015-03-13 17:32:02 -07004292 if (buttonState != mLastRawState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004293 moveNeeded = true;
4294 }
4295
4296 // Dispatch pointer up events.
4297 while (!upIdBits.isEmpty()) {
4298 uint32_t upId = upIdBits.clearFirstMarkedBit();
4299
4300 dispatchMotion(when, policyFlags, mSource,
4301 AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004302 mLastCookedState.cookedPointerData.pointerProperties,
4303 mLastCookedState.cookedPointerData.pointerCoords,
4304 mLastCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004305 dispatchedIdBits, upId,
4306 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4307 dispatchedIdBits.clearBit(upId);
4308 }
4309
4310 // Dispatch move events if any of the remaining pointers moved from their old locations.
4311 // Although applications receive new locations as part of individual pointer up
4312 // events, they do not generally handle them except when presented in a move event.
4313 if (moveNeeded) {
4314 ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
4315 dispatchMotion(when, policyFlags, mSource,
4316 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004317 mCurrentCookedState.cookedPointerData.pointerProperties,
4318 mCurrentCookedState.cookedPointerData.pointerCoords,
4319 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004320 dispatchedIdBits, -1,
4321 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4322 }
4323
4324 // Dispatch pointer down events using the new pointer locations.
4325 while (!downIdBits.isEmpty()) {
4326 uint32_t downId = downIdBits.clearFirstMarkedBit();
4327 dispatchedIdBits.markBit(downId);
4328
4329 if (dispatchedIdBits.count() == 1) {
4330 // First pointer is going down. Set down time.
4331 mDownTime = when;
4332 }
4333
4334 dispatchMotion(when, policyFlags, mSource,
4335 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
Michael Wright842500e2015-03-13 17:32:02 -07004336 mCurrentCookedState.cookedPointerData.pointerProperties,
4337 mCurrentCookedState.cookedPointerData.pointerCoords,
4338 mCurrentCookedState.cookedPointerData.idToIndex,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004339 dispatchedIdBits, downId,
4340 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4341 }
4342 }
4343}
4344
4345void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
4346 if (mSentHoverEnter &&
Michael Wright842500e2015-03-13 17:32:02 -07004347 (mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()
4348 || !mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004349 int32_t metaState = getContext()->getGlobalMetaState();
4350 dispatchMotion(when, policyFlags, mSource,
Michael Wright842500e2015-03-13 17:32:02 -07004351 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastRawState.buttonState, 0,
4352 mLastCookedState.cookedPointerData.pointerProperties,
4353 mLastCookedState.cookedPointerData.pointerCoords,
4354 mLastCookedState.cookedPointerData.idToIndex,
4355 mLastCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004356 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4357 mSentHoverEnter = false;
4358 }
4359}
4360
4361void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
Michael Wright842500e2015-03-13 17:32:02 -07004362 if (mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty()
4363 && !mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004364 int32_t metaState = getContext()->getGlobalMetaState();
4365 if (!mSentHoverEnter) {
Michael Wright842500e2015-03-13 17:32:02 -07004366 dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_HOVER_ENTER,
4367 0, metaState, mCurrentRawState.buttonState, 0,
4368 mCurrentCookedState.cookedPointerData.pointerProperties,
4369 mCurrentCookedState.cookedPointerData.pointerCoords,
4370 mCurrentCookedState.cookedPointerData.idToIndex,
4371 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004372 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4373 mSentHoverEnter = true;
4374 }
4375
4376 dispatchMotion(when, policyFlags, mSource,
Michael Wright842500e2015-03-13 17:32:02 -07004377 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState,
4378 mCurrentRawState.buttonState, 0,
4379 mCurrentCookedState.cookedPointerData.pointerProperties,
4380 mCurrentCookedState.cookedPointerData.pointerCoords,
4381 mCurrentCookedState.cookedPointerData.idToIndex,
4382 mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
Michael Wrightd02c5b62014-02-10 15:10:22 -08004383 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
4384 }
4385}
4386
4387void TouchInputMapper::cookPointerData() {
Michael Wright842500e2015-03-13 17:32:02 -07004388 uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004389
Michael Wright842500e2015-03-13 17:32:02 -07004390 mCurrentCookedState.cookedPointerData.clear();
4391 mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
4392 mCurrentCookedState.cookedPointerData.hoveringIdBits =
4393 mCurrentRawState.rawPointerData.hoveringIdBits;
4394 mCurrentCookedState.cookedPointerData.touchingIdBits =
4395 mCurrentRawState.rawPointerData.touchingIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004396
4397 // Walk through the the active pointers and map device coordinates onto
4398 // surface coordinates and adjust for display orientation.
4399 for (uint32_t i = 0; i < currentPointerCount; i++) {
Michael Wright842500e2015-03-13 17:32:02 -07004400 const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08004401
4402 // Size
4403 float touchMajor, touchMinor, toolMajor, toolMinor, size;
4404 switch (mCalibration.sizeCalibration) {
4405 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
4406 case Calibration::SIZE_CALIBRATION_DIAMETER:
4407 case Calibration::SIZE_CALIBRATION_BOX:
4408 case Calibration::SIZE_CALIBRATION_AREA:
4409 if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
4410 touchMajor = in.touchMajor;
4411 touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
4412 toolMajor = in.toolMajor;
4413 toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
4414 size = mRawPointerAxes.touchMinor.valid
4415 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4416 } else if (mRawPointerAxes.touchMajor.valid) {
4417 toolMajor = touchMajor = in.touchMajor;
4418 toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
4419 ? in.touchMinor : in.touchMajor;
4420 size = mRawPointerAxes.touchMinor.valid
4421 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
4422 } else if (mRawPointerAxes.toolMajor.valid) {
4423 touchMajor = toolMajor = in.toolMajor;
4424 touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
4425 ? in.toolMinor : in.toolMajor;
4426 size = mRawPointerAxes.toolMinor.valid
4427 ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
4428 } else {
4429 ALOG_ASSERT(false, "No touch or tool axes. "
4430 "Size calibration should have been resolved to NONE.");
4431 touchMajor = 0;
4432 touchMinor = 0;
4433 toolMajor = 0;
4434 toolMinor = 0;
4435 size = 0;
4436 }
4437
4438 if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
Michael Wright842500e2015-03-13 17:32:02 -07004439 uint32_t touchingCount =
4440 mCurrentRawState.rawPointerData.touchingIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004441 if (touchingCount > 1) {
4442 touchMajor /= touchingCount;
4443 touchMinor /= touchingCount;
4444 toolMajor /= touchingCount;
4445 toolMinor /= touchingCount;
4446 size /= touchingCount;
4447 }
4448 }
4449
4450 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
4451 touchMajor *= mGeometricScale;
4452 touchMinor *= mGeometricScale;
4453 toolMajor *= mGeometricScale;
4454 toolMinor *= mGeometricScale;
4455 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
4456 touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
4457 touchMinor = touchMajor;
4458 toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
4459 toolMinor = toolMajor;
4460 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
4461 touchMinor = touchMajor;
4462 toolMinor = toolMajor;
4463 }
4464
4465 mCalibration.applySizeScaleAndBias(&touchMajor);
4466 mCalibration.applySizeScaleAndBias(&touchMinor);
4467 mCalibration.applySizeScaleAndBias(&toolMajor);
4468 mCalibration.applySizeScaleAndBias(&toolMinor);
4469 size *= mSizeScale;
4470 break;
4471 default:
4472 touchMajor = 0;
4473 touchMinor = 0;
4474 toolMajor = 0;
4475 toolMinor = 0;
4476 size = 0;
4477 break;
4478 }
4479
4480 // Pressure
4481 float pressure;
4482 switch (mCalibration.pressureCalibration) {
4483 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
4484 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
4485 pressure = in.pressure * mPressureScale;
4486 break;
4487 default:
4488 pressure = in.isHovering ? 0 : 1;
4489 break;
4490 }
4491
4492 // Tilt and Orientation
4493 float tilt;
4494 float orientation;
4495 if (mHaveTilt) {
4496 float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
4497 float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
4498 orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
4499 tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
4500 } else {
4501 tilt = 0;
4502
4503 switch (mCalibration.orientationCalibration) {
4504 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
4505 orientation = in.orientation * mOrientationScale;
4506 break;
4507 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
4508 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
4509 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
4510 if (c1 != 0 || c2 != 0) {
4511 orientation = atan2f(c1, c2) * 0.5f;
4512 float confidence = hypotf(c1, c2);
4513 float scale = 1.0f + confidence / 16.0f;
4514 touchMajor *= scale;
4515 touchMinor /= scale;
4516 toolMajor *= scale;
4517 toolMinor /= scale;
4518 } else {
4519 orientation = 0;
4520 }
4521 break;
4522 }
4523 default:
4524 orientation = 0;
4525 }
4526 }
4527
4528 // Distance
4529 float distance;
4530 switch (mCalibration.distanceCalibration) {
4531 case Calibration::DISTANCE_CALIBRATION_SCALED:
4532 distance = in.distance * mDistanceScale;
4533 break;
4534 default:
4535 distance = 0;
4536 }
4537
4538 // Coverage
4539 int32_t rawLeft, rawTop, rawRight, rawBottom;
4540 switch (mCalibration.coverageCalibration) {
4541 case Calibration::COVERAGE_CALIBRATION_BOX:
4542 rawLeft = (in.toolMinor & 0xffff0000) >> 16;
4543 rawRight = in.toolMinor & 0x0000ffff;
4544 rawBottom = in.toolMajor & 0x0000ffff;
4545 rawTop = (in.toolMajor & 0xffff0000) >> 16;
4546 break;
4547 default:
4548 rawLeft = rawTop = rawRight = rawBottom = 0;
4549 break;
4550 }
4551
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004552 // Adjust X,Y coords for device calibration
4553 // TODO: Adjust coverage coords?
4554 float xTransformed = in.x, yTransformed = in.y;
4555 mAffineTransform.applyTo(xTransformed, yTransformed);
4556
4557 // Adjust X, Y, and coverage coords for surface orientation.
4558 float x, y;
4559 float left, top, right, bottom;
4560
Michael Wrightd02c5b62014-02-10 15:10:22 -08004561 switch (mSurfaceOrientation) {
4562 case DISPLAY_ORIENTATION_90:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004563 x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4564 y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004565 left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4566 right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4567 bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
4568 top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
4569 orientation -= M_PI_2;
4570 if (orientation < mOrientedRanges.orientation.min) {
4571 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
4572 }
4573 break;
4574 case DISPLAY_ORIENTATION_180:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004575 x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
4576 y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004577 left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
4578 right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
4579 bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
4580 top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
4581 orientation -= M_PI;
4582 if (orientation < mOrientedRanges.orientation.min) {
4583 orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
4584 }
4585 break;
4586 case DISPLAY_ORIENTATION_270:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004587 x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
4588 y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004589 left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
4590 right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
4591 bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4592 top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4593 orientation += M_PI_2;
4594 if (orientation > mOrientedRanges.orientation.max) {
4595 orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
4596 }
4597 break;
4598 default:
Jason Gereckeaf126fb2012-05-10 14:22:47 -07004599 x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4600 y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004601 left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4602 right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
4603 bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4604 top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
4605 break;
4606 }
4607
4608 // Write output coords.
Michael Wright842500e2015-03-13 17:32:02 -07004609 PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08004610 out.clear();
4611 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4612 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4613 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
4614 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
4615 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
4616 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
4617 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
4618 out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
4619 out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
4620 if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
4621 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
4622 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
4623 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
4624 out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
4625 } else {
4626 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
4627 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
4628 }
4629
4630 // Write output properties.
Michael Wright842500e2015-03-13 17:32:02 -07004631 PointerProperties& properties =
4632 mCurrentCookedState.cookedPointerData.pointerProperties[i];
Michael Wrightd02c5b62014-02-10 15:10:22 -08004633 uint32_t id = in.id;
4634 properties.clear();
4635 properties.id = id;
4636 properties.toolType = in.toolType;
4637
4638 // Write id index.
Michael Wright842500e2015-03-13 17:32:02 -07004639 mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004640 }
4641}
4642
4643void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
4644 PointerUsage pointerUsage) {
4645 if (pointerUsage != mPointerUsage) {
4646 abortPointerUsage(when, policyFlags);
4647 mPointerUsage = pointerUsage;
4648 }
4649
4650 switch (mPointerUsage) {
4651 case POINTER_USAGE_GESTURES:
4652 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
4653 break;
4654 case POINTER_USAGE_STYLUS:
4655 dispatchPointerStylus(when, policyFlags);
4656 break;
4657 case POINTER_USAGE_MOUSE:
4658 dispatchPointerMouse(when, policyFlags);
4659 break;
4660 default:
4661 break;
4662 }
4663}
4664
4665void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
4666 switch (mPointerUsage) {
4667 case POINTER_USAGE_GESTURES:
4668 abortPointerGestures(when, policyFlags);
4669 break;
4670 case POINTER_USAGE_STYLUS:
4671 abortPointerStylus(when, policyFlags);
4672 break;
4673 case POINTER_USAGE_MOUSE:
4674 abortPointerMouse(when, policyFlags);
4675 break;
4676 default:
4677 break;
4678 }
4679
4680 mPointerUsage = POINTER_USAGE_NONE;
4681}
4682
4683void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
4684 bool isTimeout) {
4685 // Update current gesture coordinates.
4686 bool cancelPreviousGesture, finishPreviousGesture;
4687 bool sendEvents = preparePointerGestures(when,
4688 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
4689 if (!sendEvents) {
4690 return;
4691 }
4692 if (finishPreviousGesture) {
4693 cancelPreviousGesture = false;
4694 }
4695
4696 // Update the pointer presentation and spots.
4697 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4698 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
4699 if (finishPreviousGesture || cancelPreviousGesture) {
4700 mPointerController->clearSpots();
4701 }
4702 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
4703 mPointerGesture.currentGestureIdToIndex,
4704 mPointerGesture.currentGestureIdBits);
4705 } else {
4706 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
4707 }
4708
4709 // Show or hide the pointer if needed.
4710 switch (mPointerGesture.currentGestureMode) {
4711 case PointerGesture::NEUTRAL:
4712 case PointerGesture::QUIET:
4713 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
4714 && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4715 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
4716 // Remind the user of where the pointer is after finishing a gesture with spots.
4717 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
4718 }
4719 break;
4720 case PointerGesture::TAP:
4721 case PointerGesture::TAP_DRAG:
4722 case PointerGesture::BUTTON_CLICK_OR_DRAG:
4723 case PointerGesture::HOVER:
4724 case PointerGesture::PRESS:
4725 // Unfade the pointer when the current gesture manipulates the
4726 // area directly under the pointer.
4727 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4728 break;
4729 case PointerGesture::SWIPE:
4730 case PointerGesture::FREEFORM:
4731 // Fade the pointer when the current gesture manipulates a different
4732 // area and there are spots to guide the user experience.
4733 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4734 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4735 } else {
4736 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4737 }
4738 break;
4739 }
4740
4741 // Send events!
4742 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright842500e2015-03-13 17:32:02 -07004743 int32_t buttonState = mCurrentRawState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004744
4745 // Update last coordinates of pointers that have moved so that we observe the new
4746 // pointer positions at the same time as other pointers that have just gone up.
4747 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
4748 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
4749 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
4750 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
4751 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
4752 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
4753 bool moveNeeded = false;
4754 if (down && !cancelPreviousGesture && !finishPreviousGesture
4755 && !mPointerGesture.lastGestureIdBits.isEmpty()
4756 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
4757 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
4758 & mPointerGesture.lastGestureIdBits.value);
4759 moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
4760 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4761 mPointerGesture.lastGestureProperties,
4762 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4763 movedGestureIdBits);
Michael Wright842500e2015-03-13 17:32:02 -07004764 if (buttonState != mLastRawState.buttonState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004765 moveNeeded = true;
4766 }
4767 }
4768
4769 // Send motion events for all pointers that went up or were canceled.
4770 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
4771 if (!dispatchedGestureIdBits.isEmpty()) {
4772 if (cancelPreviousGesture) {
4773 dispatchMotion(when, policyFlags, mSource,
4774 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4775 AMOTION_EVENT_EDGE_FLAG_NONE,
4776 mPointerGesture.lastGestureProperties,
4777 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4778 dispatchedGestureIdBits, -1,
4779 0, 0, mPointerGesture.downTime);
4780
4781 dispatchedGestureIdBits.clear();
4782 } else {
4783 BitSet32 upGestureIdBits;
4784 if (finishPreviousGesture) {
4785 upGestureIdBits = dispatchedGestureIdBits;
4786 } else {
4787 upGestureIdBits.value = dispatchedGestureIdBits.value
4788 & ~mPointerGesture.currentGestureIdBits.value;
4789 }
4790 while (!upGestureIdBits.isEmpty()) {
4791 uint32_t id = upGestureIdBits.clearFirstMarkedBit();
4792
4793 dispatchMotion(when, policyFlags, mSource,
4794 AMOTION_EVENT_ACTION_POINTER_UP, 0,
4795 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4796 mPointerGesture.lastGestureProperties,
4797 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4798 dispatchedGestureIdBits, id,
4799 0, 0, mPointerGesture.downTime);
4800
4801 dispatchedGestureIdBits.clearBit(id);
4802 }
4803 }
4804 }
4805
4806 // Send motion events for all pointers that moved.
4807 if (moveNeeded) {
4808 dispatchMotion(when, policyFlags, mSource,
4809 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4810 mPointerGesture.currentGestureProperties,
4811 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4812 dispatchedGestureIdBits, -1,
4813 0, 0, mPointerGesture.downTime);
4814 }
4815
4816 // Send motion events for all pointers that went down.
4817 if (down) {
4818 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
4819 & ~dispatchedGestureIdBits.value);
4820 while (!downGestureIdBits.isEmpty()) {
4821 uint32_t id = downGestureIdBits.clearFirstMarkedBit();
4822 dispatchedGestureIdBits.markBit(id);
4823
4824 if (dispatchedGestureIdBits.count() == 1) {
4825 mPointerGesture.downTime = when;
4826 }
4827
4828 dispatchMotion(when, policyFlags, mSource,
4829 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
4830 mPointerGesture.currentGestureProperties,
4831 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4832 dispatchedGestureIdBits, id,
4833 0, 0, mPointerGesture.downTime);
4834 }
4835 }
4836
4837 // Send motion events for hover.
4838 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
4839 dispatchMotion(when, policyFlags, mSource,
4840 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4841 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4842 mPointerGesture.currentGestureProperties,
4843 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4844 mPointerGesture.currentGestureIdBits, -1,
4845 0, 0, mPointerGesture.downTime);
4846 } else if (dispatchedGestureIdBits.isEmpty()
4847 && !mPointerGesture.lastGestureIdBits.isEmpty()) {
4848 // Synthesize a hover move event after all pointers go up to indicate that
4849 // the pointer is hovering again even if the user is not currently touching
4850 // the touch pad. This ensures that a view will receive a fresh hover enter
4851 // event after a tap.
4852 float x, y;
4853 mPointerController->getPosition(&x, &y);
4854
4855 PointerProperties pointerProperties;
4856 pointerProperties.clear();
4857 pointerProperties.id = 0;
4858 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
4859
4860 PointerCoords pointerCoords;
4861 pointerCoords.clear();
4862 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4863 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4864
4865 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
4866 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4867 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4868 mViewport.displayId, 1, &pointerProperties, &pointerCoords,
4869 0, 0, mPointerGesture.downTime);
4870 getListener()->notifyMotion(&args);
4871 }
4872
4873 // Update state.
4874 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
4875 if (!down) {
4876 mPointerGesture.lastGestureIdBits.clear();
4877 } else {
4878 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
4879 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
4880 uint32_t id = idBits.clearFirstMarkedBit();
4881 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4882 mPointerGesture.lastGestureProperties[index].copyFrom(
4883 mPointerGesture.currentGestureProperties[index]);
4884 mPointerGesture.lastGestureCoords[index].copyFrom(
4885 mPointerGesture.currentGestureCoords[index]);
4886 mPointerGesture.lastGestureIdToIndex[id] = index;
4887 }
4888 }
4889}
4890
4891void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
4892 // Cancel previously dispatches pointers.
4893 if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
4894 int32_t metaState = getContext()->getGlobalMetaState();
Michael Wright842500e2015-03-13 17:32:02 -07004895 int32_t buttonState = mCurrentRawState.buttonState;
Michael Wrightd02c5b62014-02-10 15:10:22 -08004896 dispatchMotion(when, policyFlags, mSource,
4897 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4898 AMOTION_EVENT_EDGE_FLAG_NONE,
4899 mPointerGesture.lastGestureProperties,
4900 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4901 mPointerGesture.lastGestureIdBits, -1,
4902 0, 0, mPointerGesture.downTime);
4903 }
4904
4905 // Reset the current pointer gesture.
4906 mPointerGesture.reset();
4907 mPointerVelocityControl.reset();
4908
4909 // Remove any current spots.
4910 if (mPointerController != NULL) {
4911 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4912 mPointerController->clearSpots();
4913 }
4914}
4915
4916bool TouchInputMapper::preparePointerGestures(nsecs_t when,
4917 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
4918 *outCancelPreviousGesture = false;
4919 *outFinishPreviousGesture = false;
4920
4921 // Handle TAP timeout.
4922 if (isTimeout) {
4923#if DEBUG_GESTURES
4924 ALOGD("Gestures: Processing timeout");
4925#endif
4926
4927 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
4928 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
4929 // The tap/drag timeout has not yet expired.
4930 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
4931 + mConfig.pointerGestureTapDragInterval);
4932 } else {
4933 // The tap is finished.
4934#if DEBUG_GESTURES
4935 ALOGD("Gestures: TAP finished");
4936#endif
4937 *outFinishPreviousGesture = true;
4938
4939 mPointerGesture.activeGestureId = -1;
4940 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4941 mPointerGesture.currentGestureIdBits.clear();
4942
4943 mPointerVelocityControl.reset();
4944 return true;
4945 }
4946 }
4947
4948 // We did not handle this timeout.
4949 return false;
4950 }
4951
Michael Wright842500e2015-03-13 17:32:02 -07004952 const uint32_t currentFingerCount = mCurrentCookedState.fingerIdBits.count();
4953 const uint32_t lastFingerCount = mLastCookedState.fingerIdBits.count();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004954
4955 // Update the velocity tracker.
4956 {
4957 VelocityTracker::Position positions[MAX_POINTERS];
4958 uint32_t count = 0;
Michael Wright842500e2015-03-13 17:32:02 -07004959 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); count++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004960 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07004961 const RawPointerData::Pointer& pointer =
4962 mCurrentRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004963 positions[count].x = pointer.x * mPointerXMovementScale;
4964 positions[count].y = pointer.y * mPointerYMovementScale;
4965 }
4966 mPointerGesture.velocityTracker.addMovement(when,
Michael Wright842500e2015-03-13 17:32:02 -07004967 mCurrentCookedState.fingerIdBits, positions);
Michael Wrightd02c5b62014-02-10 15:10:22 -08004968 }
4969
4970 // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
4971 // to NEUTRAL, then we should not generate tap event.
4972 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
4973 && mPointerGesture.lastGestureMode != PointerGesture::TAP
4974 && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
4975 mPointerGesture.resetTap();
4976 }
4977
4978 // Pick a new active touch id if needed.
4979 // Choose an arbitrary pointer that just went down, if there is one.
4980 // Otherwise choose an arbitrary remaining pointer.
4981 // This guarantees we always have an active touch id when there is at least one pointer.
4982 // We keep the same active touch id for as long as possible.
4983 bool activeTouchChanged = false;
4984 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
4985 int32_t activeTouchId = lastActiveTouchId;
4986 if (activeTouchId < 0) {
Michael Wright842500e2015-03-13 17:32:02 -07004987 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004988 activeTouchChanged = true;
4989 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07004990 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004991 mPointerGesture.firstTouchTime = when;
4992 }
Michael Wright842500e2015-03-13 17:32:02 -07004993 } else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004994 activeTouchChanged = true;
Michael Wright842500e2015-03-13 17:32:02 -07004995 if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08004996 activeTouchId = mPointerGesture.activeTouchId =
Michael Wright842500e2015-03-13 17:32:02 -07004997 mCurrentCookedState.fingerIdBits.firstMarkedBit();
Michael Wrightd02c5b62014-02-10 15:10:22 -08004998 } else {
4999 activeTouchId = mPointerGesture.activeTouchId = -1;
5000 }
5001 }
5002
5003 // Determine whether we are in quiet time.
5004 bool isQuietTime = false;
5005 if (activeTouchId < 0) {
5006 mPointerGesture.resetQuietTime();
5007 } else {
5008 isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
5009 if (!isQuietTime) {
5010 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
5011 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
5012 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
5013 && currentFingerCount < 2) {
5014 // Enter quiet time when exiting swipe or freeform state.
5015 // This is to prevent accidentally entering the hover state and flinging the
5016 // pointer when finishing a swipe and there is still one pointer left onscreen.
5017 isQuietTime = true;
5018 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
5019 && currentFingerCount >= 2
Michael Wright842500e2015-03-13 17:32:02 -07005020 && !isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005021 // Enter quiet time when releasing the button and there are still two or more
5022 // fingers down. This may indicate that one finger was used to press the button
5023 // but it has not gone up yet.
5024 isQuietTime = true;
5025 }
5026 if (isQuietTime) {
5027 mPointerGesture.quietTime = when;
5028 }
5029 }
5030 }
5031
5032 // Switch states based on button and pointer state.
5033 if (isQuietTime) {
5034 // Case 1: Quiet time. (QUIET)
5035#if DEBUG_GESTURES
5036 ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
5037 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
5038#endif
5039 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
5040 *outFinishPreviousGesture = true;
5041 }
5042
5043 mPointerGesture.activeGestureId = -1;
5044 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
5045 mPointerGesture.currentGestureIdBits.clear();
5046
5047 mPointerVelocityControl.reset();
Michael Wright842500e2015-03-13 17:32:02 -07005048 } else if (isPointerDown(mCurrentRawState.buttonState)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005049 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
5050 // The pointer follows the active touch point.
5051 // Emit DOWN, MOVE, UP events at the pointer location.
5052 //
5053 // Only the active touch matters; other fingers are ignored. This policy helps
5054 // to handle the case where the user places a second finger on the touch pad
5055 // to apply the necessary force to depress an integrated button below the surface.
5056 // We don't want the second finger to be delivered to applications.
5057 //
5058 // For this to work well, we need to make sure to track the pointer that is really
5059 // active. If the user first puts one finger down to click then adds another
5060 // finger to drag then the active pointer should switch to the finger that is
5061 // being dragged.
5062#if DEBUG_GESTURES
5063 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
5064 "currentFingerCount=%d", activeTouchId, currentFingerCount);
5065#endif
5066 // Reset state when just starting.
5067 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
5068 *outFinishPreviousGesture = true;
5069 mPointerGesture.activeGestureId = 0;
5070 }
5071
5072 // Switch pointers if needed.
5073 // Find the fastest pointer and follow it.
5074 if (activeTouchId >= 0 && currentFingerCount > 1) {
5075 int32_t bestId = -1;
5076 float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
Michael Wright842500e2015-03-13 17:32:02 -07005077 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty(); ) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005078 uint32_t id = idBits.clearFirstMarkedBit();
5079 float vx, vy;
5080 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
5081 float speed = hypotf(vx, vy);
5082 if (speed > bestSpeed) {
5083 bestId = id;
5084 bestSpeed = speed;
5085 }
5086 }
5087 }
5088 if (bestId >= 0 && bestId != activeTouchId) {
5089 mPointerGesture.activeTouchId = activeTouchId = bestId;
5090 activeTouchChanged = true;
5091#if DEBUG_GESTURES
5092 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
5093 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
5094#endif
5095 }
5096 }
5097
Michael Wright842500e2015-03-13 17:32:02 -07005098 if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005099 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005100 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005101 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005102 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005103 float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
5104 float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
5105
5106 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5107 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5108
5109 // Move the pointer using a relative motion.
5110 // When using spots, the click will occur at the position of the anchor
5111 // spot and all other spots will move there.
5112 mPointerController->move(deltaX, deltaY);
5113 } else {
5114 mPointerVelocityControl.reset();
5115 }
5116
5117 float x, y;
5118 mPointerController->getPosition(&x, &y);
5119
5120 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
5121 mPointerGesture.currentGestureIdBits.clear();
5122 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5123 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5124 mPointerGesture.currentGestureProperties[0].clear();
5125 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5126 mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5127 mPointerGesture.currentGestureCoords[0].clear();
5128 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5129 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5130 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5131 } else if (currentFingerCount == 0) {
5132 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
5133 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
5134 *outFinishPreviousGesture = true;
5135 }
5136
5137 // Watch for taps coming out of HOVER or TAP_DRAG mode.
5138 // Checking for taps after TAP_DRAG allows us to detect double-taps.
5139 bool tapped = false;
5140 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
5141 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
5142 && lastFingerCount == 1) {
5143 if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
5144 float x, y;
5145 mPointerController->getPosition(&x, &y);
5146 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5147 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5148#if DEBUG_GESTURES
5149 ALOGD("Gestures: TAP");
5150#endif
5151
5152 mPointerGesture.tapUpTime = when;
5153 getContext()->requestTimeoutAtTime(when
5154 + mConfig.pointerGestureTapDragInterval);
5155
5156 mPointerGesture.activeGestureId = 0;
5157 mPointerGesture.currentGestureMode = PointerGesture::TAP;
5158 mPointerGesture.currentGestureIdBits.clear();
5159 mPointerGesture.currentGestureIdBits.markBit(
5160 mPointerGesture.activeGestureId);
5161 mPointerGesture.currentGestureIdToIndex[
5162 mPointerGesture.activeGestureId] = 0;
5163 mPointerGesture.currentGestureProperties[0].clear();
5164 mPointerGesture.currentGestureProperties[0].id =
5165 mPointerGesture.activeGestureId;
5166 mPointerGesture.currentGestureProperties[0].toolType =
5167 AMOTION_EVENT_TOOL_TYPE_FINGER;
5168 mPointerGesture.currentGestureCoords[0].clear();
5169 mPointerGesture.currentGestureCoords[0].setAxisValue(
5170 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
5171 mPointerGesture.currentGestureCoords[0].setAxisValue(
5172 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
5173 mPointerGesture.currentGestureCoords[0].setAxisValue(
5174 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5175
5176 tapped = true;
5177 } else {
5178#if DEBUG_GESTURES
5179 ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
5180 x - mPointerGesture.tapX,
5181 y - mPointerGesture.tapY);
5182#endif
5183 }
5184 } else {
5185#if DEBUG_GESTURES
5186 if (mPointerGesture.tapDownTime != LLONG_MIN) {
5187 ALOGD("Gestures: Not a TAP, %0.3fms since down",
5188 (when - mPointerGesture.tapDownTime) * 0.000001f);
5189 } else {
5190 ALOGD("Gestures: Not a TAP, incompatible mode transitions");
5191 }
5192#endif
5193 }
5194 }
5195
5196 mPointerVelocityControl.reset();
5197
5198 if (!tapped) {
5199#if DEBUG_GESTURES
5200 ALOGD("Gestures: NEUTRAL");
5201#endif
5202 mPointerGesture.activeGestureId = -1;
5203 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
5204 mPointerGesture.currentGestureIdBits.clear();
5205 }
5206 } else if (currentFingerCount == 1) {
5207 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
5208 // The pointer follows the active touch point.
5209 // When in HOVER, emit HOVER_MOVE events at the pointer location.
5210 // When in TAP_DRAG, emit MOVE events at the pointer location.
5211 ALOG_ASSERT(activeTouchId >= 0);
5212
5213 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
5214 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
5215 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
5216 float x, y;
5217 mPointerController->getPosition(&x, &y);
5218 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
5219 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
5220 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5221 } else {
5222#if DEBUG_GESTURES
5223 ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
5224 x - mPointerGesture.tapX,
5225 y - mPointerGesture.tapY);
5226#endif
5227 }
5228 } else {
5229#if DEBUG_GESTURES
5230 ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
5231 (when - mPointerGesture.tapUpTime) * 0.000001f);
5232#endif
5233 }
5234 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
5235 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
5236 }
5237
Michael Wright842500e2015-03-13 17:32:02 -07005238 if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08005239 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005240 mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005241 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07005242 mLastRawState.rawPointerData.pointerForId(activeTouchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005243 float deltaX = (currentPointer.x - lastPointer.x)
5244 * mPointerXMovementScale;
5245 float deltaY = (currentPointer.y - lastPointer.y)
5246 * mPointerYMovementScale;
5247
5248 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5249 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5250
5251 // Move the pointer using a relative motion.
5252 // When using spots, the hover or drag will occur at the position of the anchor spot.
5253 mPointerController->move(deltaX, deltaY);
5254 } else {
5255 mPointerVelocityControl.reset();
5256 }
5257
5258 bool down;
5259 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
5260#if DEBUG_GESTURES
5261 ALOGD("Gestures: TAP_DRAG");
5262#endif
5263 down = true;
5264 } else {
5265#if DEBUG_GESTURES
5266 ALOGD("Gestures: HOVER");
5267#endif
5268 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
5269 *outFinishPreviousGesture = true;
5270 }
5271 mPointerGesture.activeGestureId = 0;
5272 down = false;
5273 }
5274
5275 float x, y;
5276 mPointerController->getPosition(&x, &y);
5277
5278 mPointerGesture.currentGestureIdBits.clear();
5279 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5280 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5281 mPointerGesture.currentGestureProperties[0].clear();
5282 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5283 mPointerGesture.currentGestureProperties[0].toolType =
5284 AMOTION_EVENT_TOOL_TYPE_FINGER;
5285 mPointerGesture.currentGestureCoords[0].clear();
5286 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
5287 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5288 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5289 down ? 1.0f : 0.0f);
5290
5291 if (lastFingerCount == 0 && currentFingerCount != 0) {
5292 mPointerGesture.resetTap();
5293 mPointerGesture.tapDownTime = when;
5294 mPointerGesture.tapX = x;
5295 mPointerGesture.tapY = y;
5296 }
5297 } else {
5298 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
5299 // We need to provide feedback for each finger that goes down so we cannot wait
5300 // for the fingers to move before deciding what to do.
5301 //
5302 // The ambiguous case is deciding what to do when there are two fingers down but they
5303 // have not moved enough to determine whether they are part of a drag or part of a
5304 // freeform gesture, or just a press or long-press at the pointer location.
5305 //
5306 // When there are two fingers we start with the PRESS hypothesis and we generate a
5307 // down at the pointer location.
5308 //
5309 // When the two fingers move enough or when additional fingers are added, we make
5310 // a decision to transition into SWIPE or FREEFORM mode accordingly.
5311 ALOG_ASSERT(activeTouchId >= 0);
5312
5313 bool settled = when >= mPointerGesture.firstTouchTime
5314 + mConfig.pointerGestureMultitouchSettleInterval;
5315 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
5316 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
5317 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5318 *outFinishPreviousGesture = true;
5319 } else if (!settled && currentFingerCount > lastFingerCount) {
5320 // Additional pointers have gone down but not yet settled.
5321 // Reset the gesture.
5322#if DEBUG_GESTURES
5323 ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
5324 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5325 + mConfig.pointerGestureMultitouchSettleInterval - when)
5326 * 0.000001f);
5327#endif
5328 *outCancelPreviousGesture = true;
5329 } else {
5330 // Continue previous gesture.
5331 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
5332 }
5333
5334 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
5335 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
5336 mPointerGesture.activeGestureId = 0;
5337 mPointerGesture.referenceIdBits.clear();
5338 mPointerVelocityControl.reset();
5339
5340 // Use the centroid and pointer location as the reference points for the gesture.
5341#if DEBUG_GESTURES
5342 ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
5343 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
5344 + mConfig.pointerGestureMultitouchSettleInterval - when)
5345 * 0.000001f);
5346#endif
Michael Wright842500e2015-03-13 17:32:02 -07005347 mCurrentRawState.rawPointerData.getCentroidOfTouchingPointers(
Michael Wrightd02c5b62014-02-10 15:10:22 -08005348 &mPointerGesture.referenceTouchX,
5349 &mPointerGesture.referenceTouchY);
5350 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
5351 &mPointerGesture.referenceGestureY);
5352 }
5353
5354 // Clear the reference deltas for fingers not yet included in the reference calculation.
Michael Wright842500e2015-03-13 17:32:02 -07005355 for (BitSet32 idBits(mCurrentCookedState.fingerIdBits.value
Michael Wrightd02c5b62014-02-10 15:10:22 -08005356 & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
5357 uint32_t id = idBits.clearFirstMarkedBit();
5358 mPointerGesture.referenceDeltas[id].dx = 0;
5359 mPointerGesture.referenceDeltas[id].dy = 0;
5360 }
Michael Wright842500e2015-03-13 17:32:02 -07005361 mPointerGesture.referenceIdBits = mCurrentCookedState.fingerIdBits;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005362
5363 // Add delta for all fingers and calculate a common movement delta.
5364 float commonDeltaX = 0, commonDeltaY = 0;
Michael Wright842500e2015-03-13 17:32:02 -07005365 BitSet32 commonIdBits(mLastCookedState.fingerIdBits.value
5366 & mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005367 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
5368 bool first = (idBits == commonIdBits);
5369 uint32_t id = idBits.clearFirstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005370 const RawPointerData::Pointer& cpd = mCurrentRawState.rawPointerData.pointerForId(id);
5371 const RawPointerData::Pointer& lpd = mLastRawState.rawPointerData.pointerForId(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005372 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5373 delta.dx += cpd.x - lpd.x;
5374 delta.dy += cpd.y - lpd.y;
5375
5376 if (first) {
5377 commonDeltaX = delta.dx;
5378 commonDeltaY = delta.dy;
5379 } else {
5380 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
5381 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
5382 }
5383 }
5384
5385 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
5386 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
5387 float dist[MAX_POINTER_ID + 1];
5388 int32_t distOverThreshold = 0;
5389 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
5390 uint32_t id = idBits.clearFirstMarkedBit();
5391 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5392 dist[id] = hypotf(delta.dx * mPointerXZoomScale,
5393 delta.dy * mPointerYZoomScale);
5394 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
5395 distOverThreshold += 1;
5396 }
5397 }
5398
5399 // Only transition when at least two pointers have moved further than
5400 // the minimum distance threshold.
5401 if (distOverThreshold >= 2) {
5402 if (currentFingerCount > 2) {
5403 // There are more than two pointers, switch to FREEFORM.
5404#if DEBUG_GESTURES
5405 ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
5406 currentFingerCount);
5407#endif
5408 *outCancelPreviousGesture = true;
5409 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5410 } else {
5411 // There are exactly two pointers.
Michael Wright842500e2015-03-13 17:32:02 -07005412 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005413 uint32_t id1 = idBits.clearFirstMarkedBit();
5414 uint32_t id2 = idBits.firstMarkedBit();
Michael Wright842500e2015-03-13 17:32:02 -07005415 const RawPointerData::Pointer& p1 =
5416 mCurrentRawState.rawPointerData.pointerForId(id1);
5417 const RawPointerData::Pointer& p2 =
5418 mCurrentRawState.rawPointerData.pointerForId(id2);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005419 float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
5420 if (mutualDistance > mPointerGestureMaxSwipeWidth) {
5421 // There are two pointers but they are too far apart for a SWIPE,
5422 // switch to FREEFORM.
5423#if DEBUG_GESTURES
5424 ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
5425 mutualDistance, mPointerGestureMaxSwipeWidth);
5426#endif
5427 *outCancelPreviousGesture = true;
5428 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5429 } else {
5430 // There are two pointers. Wait for both pointers to start moving
5431 // before deciding whether this is a SWIPE or FREEFORM gesture.
5432 float dist1 = dist[id1];
5433 float dist2 = dist[id2];
5434 if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
5435 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
5436 // Calculate the dot product of the displacement vectors.
5437 // When the vectors are oriented in approximately the same direction,
5438 // the angle betweeen them is near zero and the cosine of the angle
5439 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
5440 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
5441 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
5442 float dx1 = delta1.dx * mPointerXZoomScale;
5443 float dy1 = delta1.dy * mPointerYZoomScale;
5444 float dx2 = delta2.dx * mPointerXZoomScale;
5445 float dy2 = delta2.dy * mPointerYZoomScale;
5446 float dot = dx1 * dx2 + dy1 * dy2;
5447 float cosine = dot / (dist1 * dist2); // denominator always > 0
5448 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
5449 // Pointers are moving in the same direction. Switch to SWIPE.
5450#if DEBUG_GESTURES
5451 ALOGD("Gestures: PRESS transitioned to SWIPE, "
5452 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
5453 "cosine %0.3f >= %0.3f",
5454 dist1, mConfig.pointerGestureMultitouchMinDistance,
5455 dist2, mConfig.pointerGestureMultitouchMinDistance,
5456 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
5457#endif
5458 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
5459 } else {
5460 // Pointers are moving in different directions. Switch to FREEFORM.
5461#if DEBUG_GESTURES
5462 ALOGD("Gestures: PRESS transitioned to FREEFORM, "
5463 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
5464 "cosine %0.3f < %0.3f",
5465 dist1, mConfig.pointerGestureMultitouchMinDistance,
5466 dist2, mConfig.pointerGestureMultitouchMinDistance,
5467 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
5468#endif
5469 *outCancelPreviousGesture = true;
5470 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5471 }
5472 }
5473 }
5474 }
5475 }
5476 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
5477 // Switch from SWIPE to FREEFORM if additional pointers go down.
5478 // Cancel previous gesture.
5479 if (currentFingerCount > 2) {
5480#if DEBUG_GESTURES
5481 ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
5482 currentFingerCount);
5483#endif
5484 *outCancelPreviousGesture = true;
5485 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
5486 }
5487 }
5488
5489 // Move the reference points based on the overall group motion of the fingers
5490 // except in PRESS mode while waiting for a transition to occur.
5491 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
5492 && (commonDeltaX || commonDeltaY)) {
5493 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
5494 uint32_t id = idBits.clearFirstMarkedBit();
5495 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
5496 delta.dx = 0;
5497 delta.dy = 0;
5498 }
5499
5500 mPointerGesture.referenceTouchX += commonDeltaX;
5501 mPointerGesture.referenceTouchY += commonDeltaY;
5502
5503 commonDeltaX *= mPointerXMovementScale;
5504 commonDeltaY *= mPointerYMovementScale;
5505
5506 rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
5507 mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
5508
5509 mPointerGesture.referenceGestureX += commonDeltaX;
5510 mPointerGesture.referenceGestureY += commonDeltaY;
5511 }
5512
5513 // Report gestures.
5514 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
5515 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
5516 // PRESS or SWIPE mode.
5517#if DEBUG_GESTURES
5518 ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
5519 "activeGestureId=%d, currentTouchPointerCount=%d",
5520 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
5521#endif
5522 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
5523
5524 mPointerGesture.currentGestureIdBits.clear();
5525 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
5526 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
5527 mPointerGesture.currentGestureProperties[0].clear();
5528 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
5529 mPointerGesture.currentGestureProperties[0].toolType =
5530 AMOTION_EVENT_TOOL_TYPE_FINGER;
5531 mPointerGesture.currentGestureCoords[0].clear();
5532 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
5533 mPointerGesture.referenceGestureX);
5534 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
5535 mPointerGesture.referenceGestureY);
5536 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5537 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
5538 // FREEFORM mode.
5539#if DEBUG_GESTURES
5540 ALOGD("Gestures: FREEFORM activeTouchId=%d,"
5541 "activeGestureId=%d, currentTouchPointerCount=%d",
5542 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
5543#endif
5544 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
5545
5546 mPointerGesture.currentGestureIdBits.clear();
5547
5548 BitSet32 mappedTouchIdBits;
5549 BitSet32 usedGestureIdBits;
5550 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
5551 // Initially, assign the active gesture id to the active touch point
5552 // if there is one. No other touch id bits are mapped yet.
5553 if (!*outCancelPreviousGesture) {
5554 mappedTouchIdBits.markBit(activeTouchId);
5555 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
5556 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
5557 mPointerGesture.activeGestureId;
5558 } else {
5559 mPointerGesture.activeGestureId = -1;
5560 }
5561 } else {
5562 // Otherwise, assume we mapped all touches from the previous frame.
5563 // Reuse all mappings that are still applicable.
Michael Wright842500e2015-03-13 17:32:02 -07005564 mappedTouchIdBits.value = mLastCookedState.fingerIdBits.value
5565 & mCurrentCookedState.fingerIdBits.value;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005566 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
5567
5568 // Check whether we need to choose a new active gesture id because the
5569 // current went went up.
Michael Wright842500e2015-03-13 17:32:02 -07005570 for (BitSet32 upTouchIdBits(mLastCookedState.fingerIdBits.value
5571 & ~mCurrentCookedState.fingerIdBits.value);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005572 !upTouchIdBits.isEmpty(); ) {
5573 uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
5574 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
5575 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
5576 mPointerGesture.activeGestureId = -1;
5577 break;
5578 }
5579 }
5580 }
5581
5582#if DEBUG_GESTURES
5583 ALOGD("Gestures: FREEFORM follow up "
5584 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
5585 "activeGestureId=%d",
5586 mappedTouchIdBits.value, usedGestureIdBits.value,
5587 mPointerGesture.activeGestureId);
5588#endif
5589
Michael Wright842500e2015-03-13 17:32:02 -07005590 BitSet32 idBits(mCurrentCookedState.fingerIdBits);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005591 for (uint32_t i = 0; i < currentFingerCount; i++) {
5592 uint32_t touchId = idBits.clearFirstMarkedBit();
5593 uint32_t gestureId;
5594 if (!mappedTouchIdBits.hasBit(touchId)) {
5595 gestureId = usedGestureIdBits.markFirstUnmarkedBit();
5596 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
5597#if DEBUG_GESTURES
5598 ALOGD("Gestures: FREEFORM "
5599 "new mapping for touch id %d -> gesture id %d",
5600 touchId, gestureId);
5601#endif
5602 } else {
5603 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
5604#if DEBUG_GESTURES
5605 ALOGD("Gestures: FREEFORM "
5606 "existing mapping for touch id %d -> gesture id %d",
5607 touchId, gestureId);
5608#endif
5609 }
5610 mPointerGesture.currentGestureIdBits.markBit(gestureId);
5611 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
5612
5613 const RawPointerData::Pointer& pointer =
Michael Wright842500e2015-03-13 17:32:02 -07005614 mCurrentRawState.rawPointerData.pointerForId(touchId);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005615 float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
5616 * mPointerXZoomScale;
5617 float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
5618 * mPointerYZoomScale;
5619 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5620
5621 mPointerGesture.currentGestureProperties[i].clear();
5622 mPointerGesture.currentGestureProperties[i].id = gestureId;
5623 mPointerGesture.currentGestureProperties[i].toolType =
5624 AMOTION_EVENT_TOOL_TYPE_FINGER;
5625 mPointerGesture.currentGestureCoords[i].clear();
5626 mPointerGesture.currentGestureCoords[i].setAxisValue(
5627 AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
5628 mPointerGesture.currentGestureCoords[i].setAxisValue(
5629 AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
5630 mPointerGesture.currentGestureCoords[i].setAxisValue(
5631 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
5632 }
5633
5634 if (mPointerGesture.activeGestureId < 0) {
5635 mPointerGesture.activeGestureId =
5636 mPointerGesture.currentGestureIdBits.firstMarkedBit();
5637#if DEBUG_GESTURES
5638 ALOGD("Gestures: FREEFORM new "
5639 "activeGestureId=%d", mPointerGesture.activeGestureId);
5640#endif
5641 }
5642 }
5643 }
5644
Michael Wright842500e2015-03-13 17:32:02 -07005645 mPointerController->setButtonState(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005646
5647#if DEBUG_GESTURES
5648 ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
5649 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
5650 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
5651 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
5652 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
5653 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
5654 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
5655 uint32_t id = idBits.clearFirstMarkedBit();
5656 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
5657 const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
5658 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
5659 ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
5660 "x=%0.3f, y=%0.3f, pressure=%0.3f",
5661 id, index, properties.toolType,
5662 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
5663 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
5664 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
5665 }
5666 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
5667 uint32_t id = idBits.clearFirstMarkedBit();
5668 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
5669 const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
5670 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
5671 ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
5672 "x=%0.3f, y=%0.3f, pressure=%0.3f",
5673 id, index, properties.toolType,
5674 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
5675 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
5676 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
5677 }
5678#endif
5679 return true;
5680}
5681
5682void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
5683 mPointerSimple.currentCoords.clear();
5684 mPointerSimple.currentProperties.clear();
5685
5686 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07005687 if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
5688 uint32_t id = mCurrentCookedState.stylusIdBits.firstMarkedBit();
5689 uint32_t index = mCurrentCookedState.cookedPointerData.idToIndex[id];
5690 float x = mCurrentCookedState.cookedPointerData.pointerCoords[index].getX();
5691 float y = mCurrentCookedState.cookedPointerData.pointerCoords[index].getY();
Michael Wrightd02c5b62014-02-10 15:10:22 -08005692 mPointerController->setPosition(x, y);
5693
Michael Wright842500e2015-03-13 17:32:02 -07005694 hovering = mCurrentCookedState.cookedPointerData.hoveringIdBits.hasBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005695 down = !hovering;
5696
5697 mPointerController->getPosition(&x, &y);
Michael Wright842500e2015-03-13 17:32:02 -07005698 mPointerSimple.currentCoords.copyFrom(
5699 mCurrentCookedState.cookedPointerData.pointerCoords[index]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005700 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5701 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5702 mPointerSimple.currentProperties.id = 0;
5703 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07005704 mCurrentCookedState.cookedPointerData.pointerProperties[index].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005705 } else {
5706 down = false;
5707 hovering = false;
5708 }
5709
5710 dispatchPointerSimple(when, policyFlags, down, hovering);
5711}
5712
5713void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
5714 abortPointerSimple(when, policyFlags);
5715}
5716
5717void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
5718 mPointerSimple.currentCoords.clear();
5719 mPointerSimple.currentProperties.clear();
5720
5721 bool down, hovering;
Michael Wright842500e2015-03-13 17:32:02 -07005722 if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
5723 uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
5724 uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
5725 if (mLastCookedState.mouseIdBits.hasBit(id)) {
5726 uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
5727 float deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
5728 - mLastRawState.rawPointerData.pointers[lastIndex].x)
Michael Wrightd02c5b62014-02-10 15:10:22 -08005729 * mPointerXMovementScale;
Michael Wright842500e2015-03-13 17:32:02 -07005730 float deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
5731 - mLastRawState.rawPointerData.pointers[lastIndex].y)
Michael Wrightd02c5b62014-02-10 15:10:22 -08005732 * mPointerYMovementScale;
5733
5734 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5735 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5736
5737 mPointerController->move(deltaX, deltaY);
5738 } else {
5739 mPointerVelocityControl.reset();
5740 }
5741
Michael Wright842500e2015-03-13 17:32:02 -07005742 down = isPointerDown(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005743 hovering = !down;
5744
5745 float x, y;
5746 mPointerController->getPosition(&x, &y);
5747 mPointerSimple.currentCoords.copyFrom(
Michael Wright842500e2015-03-13 17:32:02 -07005748 mCurrentCookedState.cookedPointerData.pointerCoords[currentIndex]);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005749 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5750 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5751 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5752 hovering ? 0.0f : 1.0f);
5753 mPointerSimple.currentProperties.id = 0;
5754 mPointerSimple.currentProperties.toolType =
Michael Wright842500e2015-03-13 17:32:02 -07005755 mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005756 } else {
5757 mPointerVelocityControl.reset();
5758
5759 down = false;
5760 hovering = false;
5761 }
5762
5763 dispatchPointerSimple(when, policyFlags, down, hovering);
5764}
5765
5766void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
5767 abortPointerSimple(when, policyFlags);
5768
5769 mPointerVelocityControl.reset();
5770}
5771
5772void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
5773 bool down, bool hovering) {
5774 int32_t metaState = getContext()->getGlobalMetaState();
5775
5776 if (mPointerController != NULL) {
5777 if (down || hovering) {
5778 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5779 mPointerController->clearSpots();
Michael Wright842500e2015-03-13 17:32:02 -07005780 mPointerController->setButtonState(mCurrentRawState.buttonState);
Michael Wrightd02c5b62014-02-10 15:10:22 -08005781 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5782 } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
5783 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5784 }
5785 }
5786
5787 if (mPointerSimple.down && !down) {
5788 mPointerSimple.down = false;
5789
5790 // Send up.
5791 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005792 AMOTION_EVENT_ACTION_UP, 0, metaState, mLastRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005793 mViewport.displayId,
5794 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5795 mOrientedXPrecision, mOrientedYPrecision,
5796 mPointerSimple.downTime);
5797 getListener()->notifyMotion(&args);
5798 }
5799
5800 if (mPointerSimple.hovering && !hovering) {
5801 mPointerSimple.hovering = false;
5802
5803 // Send hover exit.
5804 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005805 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005806 mViewport.displayId,
5807 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5808 mOrientedXPrecision, mOrientedYPrecision,
5809 mPointerSimple.downTime);
5810 getListener()->notifyMotion(&args);
5811 }
5812
5813 if (down) {
5814 if (!mPointerSimple.down) {
5815 mPointerSimple.down = true;
5816 mPointerSimple.downTime = when;
5817
5818 // Send down.
5819 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005820 AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005821 mViewport.displayId,
5822 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5823 mOrientedXPrecision, mOrientedYPrecision,
5824 mPointerSimple.downTime);
5825 getListener()->notifyMotion(&args);
5826 }
5827
5828 // Send move.
5829 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005830 AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005831 mViewport.displayId,
5832 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5833 mOrientedXPrecision, mOrientedYPrecision,
5834 mPointerSimple.downTime);
5835 getListener()->notifyMotion(&args);
5836 }
5837
5838 if (hovering) {
5839 if (!mPointerSimple.hovering) {
5840 mPointerSimple.hovering = true;
5841
5842 // Send hover enter.
5843 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005844 AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState,
5845 mCurrentRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005846 mViewport.displayId,
5847 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5848 mOrientedXPrecision, mOrientedYPrecision,
5849 mPointerSimple.downTime);
5850 getListener()->notifyMotion(&args);
5851 }
5852
5853 // Send hover move.
5854 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005855 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState,
5856 mCurrentRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005857 mViewport.displayId,
5858 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5859 mOrientedXPrecision, mOrientedYPrecision,
5860 mPointerSimple.downTime);
5861 getListener()->notifyMotion(&args);
5862 }
5863
Michael Wright842500e2015-03-13 17:32:02 -07005864 if (mCurrentRawState.rawVScroll || mCurrentRawState.rawHScroll) {
5865 float vscroll = mCurrentRawState.rawVScroll;
5866 float hscroll = mCurrentRawState.rawHScroll;
Michael Wrightd02c5b62014-02-10 15:10:22 -08005867 mWheelYVelocityControl.move(when, NULL, &vscroll);
5868 mWheelXVelocityControl.move(when, &hscroll, NULL);
5869
5870 // Send scroll.
5871 PointerCoords pointerCoords;
5872 pointerCoords.copyFrom(mPointerSimple.currentCoords);
5873 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
5874 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
5875
5876 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Michael Wright842500e2015-03-13 17:32:02 -07005877 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentRawState.buttonState, 0,
Michael Wrightd02c5b62014-02-10 15:10:22 -08005878 mViewport.displayId,
5879 1, &mPointerSimple.currentProperties, &pointerCoords,
5880 mOrientedXPrecision, mOrientedYPrecision,
5881 mPointerSimple.downTime);
5882 getListener()->notifyMotion(&args);
5883 }
5884
5885 // Save state.
5886 if (down || hovering) {
5887 mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
5888 mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
5889 } else {
5890 mPointerSimple.reset();
5891 }
5892}
5893
5894void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
5895 mPointerSimple.currentCoords.clear();
5896 mPointerSimple.currentProperties.clear();
5897
5898 dispatchPointerSimple(when, policyFlags, false, false);
5899}
5900
5901void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
5902 int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
5903 const PointerProperties* properties, const PointerCoords* coords,
5904 const uint32_t* idToIndex, BitSet32 idBits,
5905 int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
5906 PointerCoords pointerCoords[MAX_POINTERS];
5907 PointerProperties pointerProperties[MAX_POINTERS];
5908 uint32_t pointerCount = 0;
5909 while (!idBits.isEmpty()) {
5910 uint32_t id = idBits.clearFirstMarkedBit();
5911 uint32_t index = idToIndex[id];
5912 pointerProperties[pointerCount].copyFrom(properties[index]);
5913 pointerCoords[pointerCount].copyFrom(coords[index]);
5914
5915 if (changedId >= 0 && id == uint32_t(changedId)) {
5916 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
5917 }
5918
5919 pointerCount += 1;
5920 }
5921
5922 ALOG_ASSERT(pointerCount != 0);
5923
5924 if (changedId >= 0 && pointerCount == 1) {
5925 // Replace initial down and final up action.
5926 // We can compare the action without masking off the changed pointer index
5927 // because we know the index is 0.
5928 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
5929 action = AMOTION_EVENT_ACTION_DOWN;
5930 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
5931 action = AMOTION_EVENT_ACTION_UP;
5932 } else {
5933 // Can't happen.
5934 ALOG_ASSERT(false);
5935 }
5936 }
5937
5938 NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
5939 action, flags, metaState, buttonState, edgeFlags,
5940 mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
5941 xPrecision, yPrecision, downTime);
5942 getListener()->notifyMotion(&args);
5943}
5944
5945bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
5946 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
5947 PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
5948 BitSet32 idBits) const {
5949 bool changed = false;
5950 while (!idBits.isEmpty()) {
5951 uint32_t id = idBits.clearFirstMarkedBit();
5952 uint32_t inIndex = inIdToIndex[id];
5953 uint32_t outIndex = outIdToIndex[id];
5954
5955 const PointerProperties& curInProperties = inProperties[inIndex];
5956 const PointerCoords& curInCoords = inCoords[inIndex];
5957 PointerProperties& curOutProperties = outProperties[outIndex];
5958 PointerCoords& curOutCoords = outCoords[outIndex];
5959
5960 if (curInProperties != curOutProperties) {
5961 curOutProperties.copyFrom(curInProperties);
5962 changed = true;
5963 }
5964
5965 if (curInCoords != curOutCoords) {
5966 curOutCoords.copyFrom(curInCoords);
5967 changed = true;
5968 }
5969 }
5970 return changed;
5971}
5972
5973void TouchInputMapper::fadePointer() {
5974 if (mPointerController != NULL) {
5975 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5976 }
5977}
5978
Jeff Brownc9aa6282015-02-11 19:03:28 -08005979void TouchInputMapper::cancelTouch(nsecs_t when) {
5980 abortPointerUsage(when, 0 /*policyFlags*/);
5981}
5982
Michael Wrightd02c5b62014-02-10 15:10:22 -08005983bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
5984 return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
5985 && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
5986}
5987
5988const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
5989 int32_t x, int32_t y) {
5990 size_t numVirtualKeys = mVirtualKeys.size();
5991 for (size_t i = 0; i < numVirtualKeys; i++) {
5992 const VirtualKey& virtualKey = mVirtualKeys[i];
5993
5994#if DEBUG_VIRTUAL_KEYS
5995 ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
5996 "left=%d, top=%d, right=%d, bottom=%d",
5997 x, y,
5998 virtualKey.keyCode, virtualKey.scanCode,
5999 virtualKey.hitLeft, virtualKey.hitTop,
6000 virtualKey.hitRight, virtualKey.hitBottom);
6001#endif
6002
6003 if (virtualKey.isHit(x, y)) {
6004 return & virtualKey;
6005 }
6006 }
6007
6008 return NULL;
6009}
6010
Michael Wright842500e2015-03-13 17:32:02 -07006011void TouchInputMapper::assignPointerIds(const RawState* last, RawState* current) {
6012 uint32_t currentPointerCount = current->rawPointerData.pointerCount;
6013 uint32_t lastPointerCount = last->rawPointerData.pointerCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006014
Michael Wright842500e2015-03-13 17:32:02 -07006015 current->rawPointerData.clearIdBits();
Michael Wrightd02c5b62014-02-10 15:10:22 -08006016
6017 if (currentPointerCount == 0) {
6018 // No pointers to assign.
6019 return;
6020 }
6021
6022 if (lastPointerCount == 0) {
6023 // All pointers are new.
6024 for (uint32_t i = 0; i < currentPointerCount; i++) {
6025 uint32_t id = i;
Michael Wright842500e2015-03-13 17:32:02 -07006026 current->rawPointerData.pointers[i].id = id;
6027 current->rawPointerData.idToIndex[id] = i;
6028 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(i));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006029 }
6030 return;
6031 }
6032
6033 if (currentPointerCount == 1 && lastPointerCount == 1
Michael Wright842500e2015-03-13 17:32:02 -07006034 && current->rawPointerData.pointers[0].toolType
6035 == last->rawPointerData.pointers[0].toolType) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006036 // Only one pointer and no change in count so it must have the same id as before.
Michael Wright842500e2015-03-13 17:32:02 -07006037 uint32_t id = last->rawPointerData.pointers[0].id;
6038 current->rawPointerData.pointers[0].id = id;
6039 current->rawPointerData.idToIndex[id] = 0;
6040 current->rawPointerData.markIdBit(id, current->rawPointerData.isHovering(0));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006041 return;
6042 }
6043
6044 // General case.
6045 // We build a heap of squared euclidean distances between current and last pointers
6046 // associated with the current and last pointer indices. Then, we find the best
6047 // match (by distance) for each current pointer.
6048 // The pointers must have the same tool type but it is possible for them to
6049 // transition from hovering to touching or vice-versa while retaining the same id.
6050 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
6051
6052 uint32_t heapSize = 0;
6053 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
6054 currentPointerIndex++) {
6055 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
6056 lastPointerIndex++) {
6057 const RawPointerData::Pointer& currentPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006058 current->rawPointerData.pointers[currentPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006059 const RawPointerData::Pointer& lastPointer =
Michael Wright842500e2015-03-13 17:32:02 -07006060 last->rawPointerData.pointers[lastPointerIndex];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006061 if (currentPointer.toolType == lastPointer.toolType) {
6062 int64_t deltaX = currentPointer.x - lastPointer.x;
6063 int64_t deltaY = currentPointer.y - lastPointer.y;
6064
6065 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
6066
6067 // Insert new element into the heap (sift up).
6068 heap[heapSize].currentPointerIndex = currentPointerIndex;
6069 heap[heapSize].lastPointerIndex = lastPointerIndex;
6070 heap[heapSize].distance = distance;
6071 heapSize += 1;
6072 }
6073 }
6074 }
6075
6076 // Heapify
6077 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
6078 startIndex -= 1;
6079 for (uint32_t parentIndex = startIndex; ;) {
6080 uint32_t childIndex = parentIndex * 2 + 1;
6081 if (childIndex >= heapSize) {
6082 break;
6083 }
6084
6085 if (childIndex + 1 < heapSize
6086 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6087 childIndex += 1;
6088 }
6089
6090 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6091 break;
6092 }
6093
6094 swap(heap[parentIndex], heap[childIndex]);
6095 parentIndex = childIndex;
6096 }
6097 }
6098
6099#if DEBUG_POINTER_ASSIGNMENT
6100 ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
6101 for (size_t i = 0; i < heapSize; i++) {
6102 ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
6103 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6104 heap[i].distance);
6105 }
6106#endif
6107
6108 // Pull matches out by increasing order of distance.
6109 // To avoid reassigning pointers that have already been matched, the loop keeps track
6110 // of which last and current pointers have been matched using the matchedXXXBits variables.
6111 // It also tracks the used pointer id bits.
6112 BitSet32 matchedLastBits(0);
6113 BitSet32 matchedCurrentBits(0);
6114 BitSet32 usedIdBits(0);
6115 bool first = true;
6116 for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
6117 while (heapSize > 0) {
6118 if (first) {
6119 // The first time through the loop, we just consume the root element of
6120 // the heap (the one with smallest distance).
6121 first = false;
6122 } else {
6123 // Previous iterations consumed the root element of the heap.
6124 // Pop root element off of the heap (sift down).
6125 heap[0] = heap[heapSize];
6126 for (uint32_t parentIndex = 0; ;) {
6127 uint32_t childIndex = parentIndex * 2 + 1;
6128 if (childIndex >= heapSize) {
6129 break;
6130 }
6131
6132 if (childIndex + 1 < heapSize
6133 && heap[childIndex + 1].distance < heap[childIndex].distance) {
6134 childIndex += 1;
6135 }
6136
6137 if (heap[parentIndex].distance <= heap[childIndex].distance) {
6138 break;
6139 }
6140
6141 swap(heap[parentIndex], heap[childIndex]);
6142 parentIndex = childIndex;
6143 }
6144
6145#if DEBUG_POINTER_ASSIGNMENT
6146 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
6147 for (size_t i = 0; i < heapSize; i++) {
6148 ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
6149 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
6150 heap[i].distance);
6151 }
6152#endif
6153 }
6154
6155 heapSize -= 1;
6156
6157 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
6158 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
6159
6160 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
6161 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
6162
6163 matchedCurrentBits.markBit(currentPointerIndex);
6164 matchedLastBits.markBit(lastPointerIndex);
6165
Michael Wright842500e2015-03-13 17:32:02 -07006166 uint32_t id = last->rawPointerData.pointers[lastPointerIndex].id;
6167 current->rawPointerData.pointers[currentPointerIndex].id = id;
6168 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6169 current->rawPointerData.markIdBit(id,
6170 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006171 usedIdBits.markBit(id);
6172
6173#if DEBUG_POINTER_ASSIGNMENT
6174 ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
6175 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
6176#endif
6177 break;
6178 }
6179 }
6180
6181 // Assign fresh ids to pointers that were not matched in the process.
6182 for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
6183 uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
6184 uint32_t id = usedIdBits.markFirstUnmarkedBit();
6185
Michael Wright842500e2015-03-13 17:32:02 -07006186 current->rawPointerData.pointers[currentPointerIndex].id = id;
6187 current->rawPointerData.idToIndex[id] = currentPointerIndex;
6188 current->rawPointerData.markIdBit(id,
6189 current->rawPointerData.isHovering(currentPointerIndex));
Michael Wrightd02c5b62014-02-10 15:10:22 -08006190
6191#if DEBUG_POINTER_ASSIGNMENT
6192 ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
6193 currentPointerIndex, id);
6194#endif
6195 }
6196}
6197
6198int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
6199 if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
6200 return AKEY_STATE_VIRTUAL;
6201 }
6202
6203 size_t numVirtualKeys = mVirtualKeys.size();
6204 for (size_t i = 0; i < numVirtualKeys; i++) {
6205 const VirtualKey& virtualKey = mVirtualKeys[i];
6206 if (virtualKey.keyCode == keyCode) {
6207 return AKEY_STATE_UP;
6208 }
6209 }
6210
6211 return AKEY_STATE_UNKNOWN;
6212}
6213
6214int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
6215 if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
6216 return AKEY_STATE_VIRTUAL;
6217 }
6218
6219 size_t numVirtualKeys = mVirtualKeys.size();
6220 for (size_t i = 0; i < numVirtualKeys; i++) {
6221 const VirtualKey& virtualKey = mVirtualKeys[i];
6222 if (virtualKey.scanCode == scanCode) {
6223 return AKEY_STATE_UP;
6224 }
6225 }
6226
6227 return AKEY_STATE_UNKNOWN;
6228}
6229
6230bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
6231 const int32_t* keyCodes, uint8_t* outFlags) {
6232 size_t numVirtualKeys = mVirtualKeys.size();
6233 for (size_t i = 0; i < numVirtualKeys; i++) {
6234 const VirtualKey& virtualKey = mVirtualKeys[i];
6235
6236 for (size_t i = 0; i < numCodes; i++) {
6237 if (virtualKey.keyCode == keyCodes[i]) {
6238 outFlags[i] = 1;
6239 }
6240 }
6241 }
6242
6243 return true;
6244}
6245
6246
6247// --- SingleTouchInputMapper ---
6248
6249SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
6250 TouchInputMapper(device) {
6251}
6252
6253SingleTouchInputMapper::~SingleTouchInputMapper() {
6254}
6255
6256void SingleTouchInputMapper::reset(nsecs_t when) {
6257 mSingleTouchMotionAccumulator.reset(getDevice());
6258
6259 TouchInputMapper::reset(when);
6260}
6261
6262void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
6263 TouchInputMapper::process(rawEvent);
6264
6265 mSingleTouchMotionAccumulator.process(rawEvent);
6266}
6267
Michael Wright842500e2015-03-13 17:32:02 -07006268void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006269 if (mTouchButtonAccumulator.isToolActive()) {
Michael Wright842500e2015-03-13 17:32:02 -07006270 outState->rawPointerData.pointerCount = 1;
6271 outState->rawPointerData.idToIndex[0] = 0;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006272
6273 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6274 && (mTouchButtonAccumulator.isHovering()
6275 || (mRawPointerAxes.pressure.valid
6276 && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
Michael Wright842500e2015-03-13 17:32:02 -07006277 outState->rawPointerData.markIdBit(0, isHovering);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006278
Michael Wright842500e2015-03-13 17:32:02 -07006279 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[0];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006280 outPointer.id = 0;
6281 outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
6282 outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
6283 outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
6284 outPointer.touchMajor = 0;
6285 outPointer.touchMinor = 0;
6286 outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6287 outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
6288 outPointer.orientation = 0;
6289 outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
6290 outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
6291 outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
6292 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6293 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6294 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6295 }
6296 outPointer.isHovering = isHovering;
6297 }
6298}
6299
6300void SingleTouchInputMapper::configureRawPointerAxes() {
6301 TouchInputMapper::configureRawPointerAxes();
6302
6303 getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
6304 getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
6305 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
6306 getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
6307 getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
6308 getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
6309 getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
6310}
6311
6312bool SingleTouchInputMapper::hasStylus() const {
6313 return mTouchButtonAccumulator.hasStylus();
6314}
6315
6316
6317// --- MultiTouchInputMapper ---
6318
6319MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
6320 TouchInputMapper(device) {
6321}
6322
6323MultiTouchInputMapper::~MultiTouchInputMapper() {
6324}
6325
6326void MultiTouchInputMapper::reset(nsecs_t when) {
6327 mMultiTouchMotionAccumulator.reset(getDevice());
6328
6329 mPointerIdBits.clear();
6330
6331 TouchInputMapper::reset(when);
6332}
6333
6334void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
6335 TouchInputMapper::process(rawEvent);
6336
6337 mMultiTouchMotionAccumulator.process(rawEvent);
6338}
6339
Michael Wright842500e2015-03-13 17:32:02 -07006340void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
Michael Wrightd02c5b62014-02-10 15:10:22 -08006341 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
6342 size_t outCount = 0;
6343 BitSet32 newPointerIdBits;
6344
6345 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
6346 const MultiTouchMotionAccumulator::Slot* inSlot =
6347 mMultiTouchMotionAccumulator.getSlot(inIndex);
6348 if (!inSlot->isInUse()) {
6349 continue;
6350 }
6351
6352 if (outCount >= MAX_POINTERS) {
6353#if DEBUG_POINTERS
6354 ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
6355 "ignoring the rest.",
6356 getDeviceName().string(), MAX_POINTERS);
6357#endif
6358 break; // too many fingers!
6359 }
6360
Michael Wright842500e2015-03-13 17:32:02 -07006361 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
Michael Wrightd02c5b62014-02-10 15:10:22 -08006362 outPointer.x = inSlot->getX();
6363 outPointer.y = inSlot->getY();
6364 outPointer.pressure = inSlot->getPressure();
6365 outPointer.touchMajor = inSlot->getTouchMajor();
6366 outPointer.touchMinor = inSlot->getTouchMinor();
6367 outPointer.toolMajor = inSlot->getToolMajor();
6368 outPointer.toolMinor = inSlot->getToolMinor();
6369 outPointer.orientation = inSlot->getOrientation();
6370 outPointer.distance = inSlot->getDistance();
6371 outPointer.tiltX = 0;
6372 outPointer.tiltY = 0;
6373
6374 outPointer.toolType = inSlot->getToolType();
6375 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6376 outPointer.toolType = mTouchButtonAccumulator.getToolType();
6377 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
6378 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
6379 }
6380 }
6381
6382 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
6383 && (mTouchButtonAccumulator.isHovering()
6384 || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
6385 outPointer.isHovering = isHovering;
6386
6387 // Assign pointer id using tracking id if available.
Michael Wright842500e2015-03-13 17:32:02 -07006388 mHavePointerIds = true;
6389 int32_t trackingId = inSlot->getTrackingId();
6390 int32_t id = -1;
6391 if (trackingId >= 0) {
6392 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
6393 uint32_t n = idBits.clearFirstMarkedBit();
6394 if (mPointerTrackingIdMap[n] == trackingId) {
6395 id = n;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006396 }
Michael Wright842500e2015-03-13 17:32:02 -07006397 }
Michael Wrightd02c5b62014-02-10 15:10:22 -08006398
Michael Wright842500e2015-03-13 17:32:02 -07006399 if (id < 0 && !mPointerIdBits.isFull()) {
6400 id = mPointerIdBits.markFirstUnmarkedBit();
6401 mPointerTrackingIdMap[id] = trackingId;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006402 }
Michael Wright842500e2015-03-13 17:32:02 -07006403 }
6404 if (id < 0) {
6405 mHavePointerIds = false;
6406 outState->rawPointerData.clearIdBits();
6407 newPointerIdBits.clear();
6408 } else {
6409 outPointer.id = id;
6410 outState->rawPointerData.idToIndex[id] = outCount;
6411 outState->rawPointerData.markIdBit(id, isHovering);
6412 newPointerIdBits.markBit(id);
Michael Wrightd02c5b62014-02-10 15:10:22 -08006413 }
6414
6415 outCount += 1;
6416 }
6417
Michael Wright842500e2015-03-13 17:32:02 -07006418 outState->rawPointerData.pointerCount = outCount;
Michael Wrightd02c5b62014-02-10 15:10:22 -08006419 mPointerIdBits = newPointerIdBits;
6420
6421 mMultiTouchMotionAccumulator.finishSync();
6422}
6423
6424void MultiTouchInputMapper::configureRawPointerAxes() {
6425 TouchInputMapper::configureRawPointerAxes();
6426
6427 getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
6428 getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
6429 getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
6430 getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
6431 getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
6432 getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
6433 getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
6434 getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
6435 getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
6436 getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
6437 getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
6438
6439 if (mRawPointerAxes.trackingId.valid
6440 && mRawPointerAxes.slot.valid
6441 && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
6442 size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
6443 if (slotCount > MAX_SLOTS) {
Narayan Kamath37764c72014-03-27 14:21:09 +00006444 ALOGW("MultiTouch Device %s reported %zu slots but the framework "
6445 "only supports a maximum of %zu slots at this time.",
Michael Wrightd02c5b62014-02-10 15:10:22 -08006446 getDeviceName().string(), slotCount, MAX_SLOTS);
6447 slotCount = MAX_SLOTS;
6448 }
6449 mMultiTouchMotionAccumulator.configure(getDevice(),
6450 slotCount, true /*usingSlotsProtocol*/);
6451 } else {
6452 mMultiTouchMotionAccumulator.configure(getDevice(),
6453 MAX_POINTERS, false /*usingSlotsProtocol*/);
6454 }
6455}
6456
6457bool MultiTouchInputMapper::hasStylus() const {
6458 return mMultiTouchMotionAccumulator.hasStylus()
6459 || mTouchButtonAccumulator.hasStylus();
6460}
6461
Michael Wright842500e2015-03-13 17:32:02 -07006462// --- ExternalStylusInputMapper
6463
6464ExternalStylusInputMapper::ExternalStylusInputMapper(InputDevice* device) :
6465 InputMapper(device) {
6466
6467}
6468
6469uint32_t ExternalStylusInputMapper::getSources() {
6470 return AINPUT_SOURCE_STYLUS;
6471}
6472
6473void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
6474 InputMapper::populateDeviceInfo(info);
6475 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS,
6476 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
6477}
6478
6479void ExternalStylusInputMapper::dump(String8& dump) {
6480 dump.append(INDENT2 "External Stylus Input Mapper:\n");
6481 dump.append(INDENT3 "Raw Stylus Axes:\n");
6482 dumpRawAbsoluteAxisInfo(dump, mRawPressureAxis, "Pressure");
6483 dump.append(INDENT3 "Stylus State:\n");
6484 dumpStylusState(dump, mStylusState);
6485}
6486
6487void ExternalStylusInputMapper::configure(nsecs_t when,
6488 const InputReaderConfiguration* config, uint32_t changes) {
6489 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis);
6490 mTouchButtonAccumulator.configure(getDevice());
6491}
6492
6493void ExternalStylusInputMapper::reset(nsecs_t when) {
6494 InputDevice* device = getDevice();
6495 mSingleTouchMotionAccumulator.reset(device);
6496 mTouchButtonAccumulator.reset(device);
6497 InputMapper::reset(when);
6498}
6499
6500void ExternalStylusInputMapper::process(const RawEvent* rawEvent) {
6501 mSingleTouchMotionAccumulator.process(rawEvent);
6502 mTouchButtonAccumulator.process(rawEvent);
6503
6504 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
6505 sync(rawEvent->when);
6506 }
6507}
6508
6509void ExternalStylusInputMapper::sync(nsecs_t when) {
6510 mStylusState.clear();
6511
6512 mStylusState.when = when;
6513
6514 int32_t pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
6515 if (mRawPressureAxis.valid) {
6516 mStylusState.pressure = float(pressure) / mRawPressureAxis.maxValue;
6517 } else if (mTouchButtonAccumulator.isToolActive()) {
6518 mStylusState.pressure = 1.0f;
6519 } else {
6520 mStylusState.pressure = 0.0f;
6521 }
6522
6523 mStylusState.buttons = mTouchButtonAccumulator.getButtonState();
6524 mStylusState.toolType = mTouchButtonAccumulator.getToolType();
6525
6526 mContext->dispatchExternalStylusState(mStylusState);
6527}
6528
Michael Wrightd02c5b62014-02-10 15:10:22 -08006529
6530// --- JoystickInputMapper ---
6531
6532JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
6533 InputMapper(device) {
6534}
6535
6536JoystickInputMapper::~JoystickInputMapper() {
6537}
6538
6539uint32_t JoystickInputMapper::getSources() {
6540 return AINPUT_SOURCE_JOYSTICK;
6541}
6542
6543void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
6544 InputMapper::populateDeviceInfo(info);
6545
6546 for (size_t i = 0; i < mAxes.size(); i++) {
6547 const Axis& axis = mAxes.valueAt(i);
6548 addMotionRange(axis.axisInfo.axis, axis, info);
6549
6550 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6551 addMotionRange(axis.axisInfo.highAxis, axis, info);
6552
6553 }
6554 }
6555}
6556
6557void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
6558 InputDeviceInfo* info) {
6559 info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
6560 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
6561 /* In order to ease the transition for developers from using the old axes
6562 * to the newer, more semantically correct axes, we'll continue to register
6563 * the old axes as duplicates of their corresponding new ones. */
6564 int32_t compatAxis = getCompatAxis(axisId);
6565 if (compatAxis >= 0) {
6566 info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
6567 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
6568 }
6569}
6570
6571/* A mapping from axes the joystick actually has to the axes that should be
6572 * artificially created for compatibility purposes.
6573 * Returns -1 if no compatibility axis is needed. */
6574int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
6575 switch(axis) {
6576 case AMOTION_EVENT_AXIS_LTRIGGER:
6577 return AMOTION_EVENT_AXIS_BRAKE;
6578 case AMOTION_EVENT_AXIS_RTRIGGER:
6579 return AMOTION_EVENT_AXIS_GAS;
6580 }
6581 return -1;
6582}
6583
6584void JoystickInputMapper::dump(String8& dump) {
6585 dump.append(INDENT2 "Joystick Input Mapper:\n");
6586
6587 dump.append(INDENT3 "Axes:\n");
6588 size_t numAxes = mAxes.size();
6589 for (size_t i = 0; i < numAxes; i++) {
6590 const Axis& axis = mAxes.valueAt(i);
6591 const char* label = getAxisLabel(axis.axisInfo.axis);
6592 if (label) {
6593 dump.appendFormat(INDENT4 "%s", label);
6594 } else {
6595 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
6596 }
6597 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6598 label = getAxisLabel(axis.axisInfo.highAxis);
6599 if (label) {
6600 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
6601 } else {
6602 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
6603 axis.axisInfo.splitValue);
6604 }
6605 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
6606 dump.append(" (invert)");
6607 }
6608
6609 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
6610 axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
6611 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
6612 "highScale=%0.5f, highOffset=%0.5f\n",
6613 axis.scale, axis.offset, axis.highScale, axis.highOffset);
6614 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
6615 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
6616 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
6617 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
6618 }
6619}
6620
6621void JoystickInputMapper::configure(nsecs_t when,
6622 const InputReaderConfiguration* config, uint32_t changes) {
6623 InputMapper::configure(when, config, changes);
6624
6625 if (!changes) { // first time only
6626 // Collect all axes.
6627 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
6628 if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
6629 & INPUT_DEVICE_CLASS_JOYSTICK)) {
6630 continue; // axis must be claimed by a different device
6631 }
6632
6633 RawAbsoluteAxisInfo rawAxisInfo;
6634 getAbsoluteAxisInfo(abs, &rawAxisInfo);
6635 if (rawAxisInfo.valid) {
6636 // Map axis.
6637 AxisInfo axisInfo;
6638 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
6639 if (!explicitlyMapped) {
6640 // Axis is not explicitly mapped, will choose a generic axis later.
6641 axisInfo.mode = AxisInfo::MODE_NORMAL;
6642 axisInfo.axis = -1;
6643 }
6644
6645 // Apply flat override.
6646 int32_t rawFlat = axisInfo.flatOverride < 0
6647 ? rawAxisInfo.flat : axisInfo.flatOverride;
6648
6649 // Calculate scaling factors and limits.
6650 Axis axis;
6651 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
6652 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
6653 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
6654 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
6655 scale, 0.0f, highScale, 0.0f,
6656 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
6657 rawAxisInfo.resolution * scale);
6658 } else if (isCenteredAxis(axisInfo.axis)) {
6659 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
6660 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
6661 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
6662 scale, offset, scale, offset,
6663 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
6664 rawAxisInfo.resolution * scale);
6665 } else {
6666 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
6667 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
6668 scale, 0.0f, scale, 0.0f,
6669 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
6670 rawAxisInfo.resolution * scale);
6671 }
6672
6673 // To eliminate noise while the joystick is at rest, filter out small variations
6674 // in axis values up front.
6675 axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
6676
6677 mAxes.add(abs, axis);
6678 }
6679 }
6680
6681 // If there are too many axes, start dropping them.
6682 // Prefer to keep explicitly mapped axes.
6683 if (mAxes.size() > PointerCoords::MAX_AXES) {
Narayan Kamath37764c72014-03-27 14:21:09 +00006684 ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
Michael Wrightd02c5b62014-02-10 15:10:22 -08006685 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
6686 pruneAxes(true);
6687 pruneAxes(false);
6688 }
6689
6690 // Assign generic axis ids to remaining axes.
6691 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
6692 size_t numAxes = mAxes.size();
6693 for (size_t i = 0; i < numAxes; i++) {
6694 Axis& axis = mAxes.editValueAt(i);
6695 if (axis.axisInfo.axis < 0) {
6696 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
6697 && haveAxis(nextGenericAxisId)) {
6698 nextGenericAxisId += 1;
6699 }
6700
6701 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
6702 axis.axisInfo.axis = nextGenericAxisId;
6703 nextGenericAxisId += 1;
6704 } else {
6705 ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
6706 "have already been assigned to other axes.",
6707 getDeviceName().string(), mAxes.keyAt(i));
6708 mAxes.removeItemsAt(i--);
6709 numAxes -= 1;
6710 }
6711 }
6712 }
6713 }
6714}
6715
6716bool JoystickInputMapper::haveAxis(int32_t axisId) {
6717 size_t numAxes = mAxes.size();
6718 for (size_t i = 0; i < numAxes; i++) {
6719 const Axis& axis = mAxes.valueAt(i);
6720 if (axis.axisInfo.axis == axisId
6721 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
6722 && axis.axisInfo.highAxis == axisId)) {
6723 return true;
6724 }
6725 }
6726 return false;
6727}
6728
6729void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
6730 size_t i = mAxes.size();
6731 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
6732 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
6733 continue;
6734 }
6735 ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
6736 getDeviceName().string(), mAxes.keyAt(i));
6737 mAxes.removeItemsAt(i);
6738 }
6739}
6740
6741bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
6742 switch (axis) {
6743 case AMOTION_EVENT_AXIS_X:
6744 case AMOTION_EVENT_AXIS_Y:
6745 case AMOTION_EVENT_AXIS_Z:
6746 case AMOTION_EVENT_AXIS_RX:
6747 case AMOTION_EVENT_AXIS_RY:
6748 case AMOTION_EVENT_AXIS_RZ:
6749 case AMOTION_EVENT_AXIS_HAT_X:
6750 case AMOTION_EVENT_AXIS_HAT_Y:
6751 case AMOTION_EVENT_AXIS_ORIENTATION:
6752 case AMOTION_EVENT_AXIS_RUDDER:
6753 case AMOTION_EVENT_AXIS_WHEEL:
6754 return true;
6755 default:
6756 return false;
6757 }
6758}
6759
6760void JoystickInputMapper::reset(nsecs_t when) {
6761 // Recenter all axes.
6762 size_t numAxes = mAxes.size();
6763 for (size_t i = 0; i < numAxes; i++) {
6764 Axis& axis = mAxes.editValueAt(i);
6765 axis.resetValue();
6766 }
6767
6768 InputMapper::reset(when);
6769}
6770
6771void JoystickInputMapper::process(const RawEvent* rawEvent) {
6772 switch (rawEvent->type) {
6773 case EV_ABS: {
6774 ssize_t index = mAxes.indexOfKey(rawEvent->code);
6775 if (index >= 0) {
6776 Axis& axis = mAxes.editValueAt(index);
6777 float newValue, highNewValue;
6778 switch (axis.axisInfo.mode) {
6779 case AxisInfo::MODE_INVERT:
6780 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
6781 * axis.scale + axis.offset;
6782 highNewValue = 0.0f;
6783 break;
6784 case AxisInfo::MODE_SPLIT:
6785 if (rawEvent->value < axis.axisInfo.splitValue) {
6786 newValue = (axis.axisInfo.splitValue - rawEvent->value)
6787 * axis.scale + axis.offset;
6788 highNewValue = 0.0f;
6789 } else if (rawEvent->value > axis.axisInfo.splitValue) {
6790 newValue = 0.0f;
6791 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
6792 * axis.highScale + axis.highOffset;
6793 } else {
6794 newValue = 0.0f;
6795 highNewValue = 0.0f;
6796 }
6797 break;
6798 default:
6799 newValue = rawEvent->value * axis.scale + axis.offset;
6800 highNewValue = 0.0f;
6801 break;
6802 }
6803 axis.newValue = newValue;
6804 axis.highNewValue = highNewValue;
6805 }
6806 break;
6807 }
6808
6809 case EV_SYN:
6810 switch (rawEvent->code) {
6811 case SYN_REPORT:
6812 sync(rawEvent->when, false /*force*/);
6813 break;
6814 }
6815 break;
6816 }
6817}
6818
6819void JoystickInputMapper::sync(nsecs_t when, bool force) {
6820 if (!filterAxes(force)) {
6821 return;
6822 }
6823
6824 int32_t metaState = mContext->getGlobalMetaState();
6825 int32_t buttonState = 0;
6826
6827 PointerProperties pointerProperties;
6828 pointerProperties.clear();
6829 pointerProperties.id = 0;
6830 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
6831
6832 PointerCoords pointerCoords;
6833 pointerCoords.clear();
6834
6835 size_t numAxes = mAxes.size();
6836 for (size_t i = 0; i < numAxes; i++) {
6837 const Axis& axis = mAxes.valueAt(i);
6838 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
6839 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6840 setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
6841 axis.highCurrentValue);
6842 }
6843 }
6844
6845 // Moving a joystick axis should not wake the device because joysticks can
6846 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
6847 // button will likely wake the device.
6848 // TODO: Use the input device configuration to control this behavior more finely.
6849 uint32_t policyFlags = 0;
6850
6851 NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
6852 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
6853 ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
6854 getListener()->notifyMotion(&args);
6855}
6856
6857void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
6858 int32_t axis, float value) {
6859 pointerCoords->setAxisValue(axis, value);
6860 /* In order to ease the transition for developers from using the old axes
6861 * to the newer, more semantically correct axes, we'll continue to produce
6862 * values for the old axes as mirrors of the value of their corresponding
6863 * new axes. */
6864 int32_t compatAxis = getCompatAxis(axis);
6865 if (compatAxis >= 0) {
6866 pointerCoords->setAxisValue(compatAxis, value);
6867 }
6868}
6869
6870bool JoystickInputMapper::filterAxes(bool force) {
6871 bool atLeastOneSignificantChange = force;
6872 size_t numAxes = mAxes.size();
6873 for (size_t i = 0; i < numAxes; i++) {
6874 Axis& axis = mAxes.editValueAt(i);
6875 if (force || hasValueChangedSignificantly(axis.filter,
6876 axis.newValue, axis.currentValue, axis.min, axis.max)) {
6877 axis.currentValue = axis.newValue;
6878 atLeastOneSignificantChange = true;
6879 }
6880 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6881 if (force || hasValueChangedSignificantly(axis.filter,
6882 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
6883 axis.highCurrentValue = axis.highNewValue;
6884 atLeastOneSignificantChange = true;
6885 }
6886 }
6887 }
6888 return atLeastOneSignificantChange;
6889}
6890
6891bool JoystickInputMapper::hasValueChangedSignificantly(
6892 float filter, float newValue, float currentValue, float min, float max) {
6893 if (newValue != currentValue) {
6894 // Filter out small changes in value unless the value is converging on the axis
6895 // bounds or center point. This is intended to reduce the amount of information
6896 // sent to applications by particularly noisy joysticks (such as PS3).
6897 if (fabs(newValue - currentValue) > filter
6898 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
6899 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
6900 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
6901 return true;
6902 }
6903 }
6904 return false;
6905}
6906
6907bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
6908 float filter, float newValue, float currentValue, float thresholdValue) {
6909 float newDistance = fabs(newValue - thresholdValue);
6910 if (newDistance < filter) {
6911 float oldDistance = fabs(currentValue - thresholdValue);
6912 if (newDistance < oldDistance) {
6913 return true;
6914 }
6915 }
6916 return false;
6917}
6918
6919} // namespace android