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