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