blob: a963c726a212773769da5fe05f9ee262d37c95bd [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -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
Jeff Brown46b9ac02010-04-22 18:58:52 -070017#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.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036#include "InputReader.h"
37
Jeff Brown46b9ac02010-04-22 18:58:52 -070038#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080039#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080040#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070045#include <errno.h>
46#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070047#include <math.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070048
Jeff Brown8d608662010-08-30 03:02:23 -070049#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070050#define INDENT2 " "
51#define INDENT3 " "
52#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070053
Jeff Brown46b9ac02010-04-22 18:58:52 -070054namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60 return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65 return a < b ? a : b;
66}
67
Jeff Brown5c225b12010-06-16 01:53:36 -070068template<typename T>
69inline static void swap(T& a, T& b) {
70 T temp = a;
71 a = b;
72 b = temp;
73}
74
Jeff Brown8d608662010-08-30 03:02:23 -070075inline static float avg(float x, float y) {
76 return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80 return sqrtf(x * x + y * y);
81}
82
Jeff Brown517bb4c2011-01-14 19:09:23 -080083inline static int32_t signExtendNybble(int32_t value) {
84 return value >= 8 ? value - 16 : value;
85}
86
Jeff Brownef3d7e82010-09-30 14:33:04 -070087static inline const char* toString(bool value) {
88 return value ? "true" : "false";
89}
90
Jeff Brown46b9ac02010-04-22 18:58:52 -070091static const int32_t keyCodeRotationMap[][4] = {
92 // key codes enumerated counter-clockwise with the original (unrotated) key first
93 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -070094 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
95 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
96 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
97 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac02010-04-22 18:58:52 -070098};
99static const int keyCodeRotationMapSize =
100 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
101
102int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103 if (orientation != DISPLAY_ORIENTATION_0) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700104 for (int i = 0; i < keyCodeRotationMapSize; i++) {
105 if (keyCode == keyCodeRotationMap[i][0]) {
106 return keyCodeRotationMap[i][orientation];
107 }
108 }
109 }
110 return keyCode;
111}
112
Jeff Brown6d0fec22010-07-23 21:28:06 -0700113static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
114 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
115}
116
Jeff Brown46b9ac02010-04-22 18:58:52 -0700117
Jeff Brown46b9ac02010-04-22 18:58:52 -0700118// --- InputReader ---
119
120InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700121 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700122 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700123 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brownfe508922011-01-18 15:10:10 -0800124 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700125 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700126 updateGlobalMetaState();
127 updateInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700128}
129
130InputReader::~InputReader() {
131 for (size_t i = 0; i < mDevices.size(); i++) {
132 delete mDevices.valueAt(i);
133 }
134}
135
136void InputReader::loopOnce() {
137 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700138 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700139
140#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800141 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
143 rawEvent.value);
144#endif
145
146 process(& rawEvent);
147}
148
149void InputReader::process(const RawEvent* rawEvent) {
150 switch (rawEvent->type) {
151 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700152 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700153 break;
154
155 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700156 removeDevice(rawEvent->deviceId);
157 break;
158
159 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700160 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700161 break;
162
Jeff Brown6d0fec22010-07-23 21:28:06 -0700163 default:
164 consumeEvent(rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700165 break;
166 }
167}
168
Jeff Brown7342bb92010-10-01 18:55:43 -0700169void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700170 String8 name = mEventHub->getDeviceName(deviceId);
171 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
172
173 InputDevice* device = createDevice(deviceId, name, classes);
174 device->configure();
175
Jeff Brown8d608662010-08-30 03:02:23 -0700176 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800177 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700178 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800179 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700180 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700181 }
182
Jeff Brown6d0fec22010-07-23 21:28:06 -0700183 bool added = false;
184 { // acquire device registry writer lock
185 RWLock::AutoWLock _wl(mDeviceRegistryLock);
186
187 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
188 if (deviceIndex < 0) {
189 mDevices.add(deviceId, device);
190 added = true;
191 }
192 } // release device registry writer lock
193
194 if (! added) {
195 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
196 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700197 return;
198 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700199}
200
Jeff Brown7342bb92010-10-01 18:55:43 -0700201void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700202 bool removed = false;
203 InputDevice* device = NULL;
204 { // acquire device registry writer lock
205 RWLock::AutoWLock _wl(mDeviceRegistryLock);
206
207 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
208 if (deviceIndex >= 0) {
209 device = mDevices.valueAt(deviceIndex);
210 mDevices.removeItemsAt(deviceIndex, 1);
211 removed = true;
212 }
213 } // release device registry writer lock
214
215 if (! removed) {
216 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800221 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 device->getId(), device->getName().string());
223 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800224 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700225 device->getId(), device->getName().string(), device->getSources());
226 }
227
Jeff Brown8d608662010-08-30 03:02:23 -0700228 device->reset();
229
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700231}
232
Jeff Brown6d0fec22010-07-23 21:28:06 -0700233InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
234 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700235
Jeff Brown6d0fec22010-07-23 21:28:06 -0700236 // Switch-like devices.
237 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
238 device->addMapper(new SwitchInputMapper(device));
239 }
240
241 // Keyboard-like devices.
242 uint32_t keyboardSources = 0;
243 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
244 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
245 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
246 }
247 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
248 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
249 }
250 if (classes & INPUT_DEVICE_CLASS_DPAD) {
251 keyboardSources |= AINPUT_SOURCE_DPAD;
252 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800253 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
254 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
255 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700256
257 if (keyboardSources != 0) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800258 device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700259 }
260
Jeff Brown83c09682010-12-23 17:50:18 -0800261 // Cursor-like devices.
262 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
263 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700264 }
265
Jeff Brown58a2da82011-01-25 16:02:22 -0800266 // Touchscreens and touchpad devices.
267 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800268 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800269 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800270 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700271 }
272
Jeff Browncb1404e2011-01-15 18:14:15 -0800273 // Joystick-like devices.
274 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
275 device->addMapper(new JoystickInputMapper(device));
276 }
277
Jeff Brown6d0fec22010-07-23 21:28:06 -0700278 return device;
279}
280
281void InputReader::consumeEvent(const RawEvent* rawEvent) {
282 int32_t deviceId = rawEvent->deviceId;
283
284 { // acquire device registry reader lock
285 RWLock::AutoRLock _rl(mDeviceRegistryLock);
286
287 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
288 if (deviceIndex < 0) {
289 LOGW("Discarding event for unknown deviceId %d.", deviceId);
290 return;
291 }
292
293 InputDevice* device = mDevices.valueAt(deviceIndex);
294 if (device->isIgnored()) {
295 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
296 return;
297 }
298
299 device->process(rawEvent);
300 } // release device registry reader lock
301}
302
Jeff Brownc3db8582010-10-20 15:33:38 -0700303void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700304 // Reset global meta state because it depends on the list of all configured devices.
305 updateGlobalMetaState();
306
307 // Update input configuration.
308 updateInputConfiguration();
309
310 // Enqueue configuration changed.
311 mDispatcher->notifyConfigurationChanged(when);
312}
313
314void InputReader::configureExcludedDevices() {
315 Vector<String8> excludedDeviceNames;
316 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
317
318 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
319 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
320 }
321}
322
323void InputReader::updateGlobalMetaState() {
324 { // acquire state lock
325 AutoMutex _l(mStateLock);
326
327 mGlobalMetaState = 0;
328
329 { // acquire device registry reader lock
330 RWLock::AutoRLock _rl(mDeviceRegistryLock);
331
332 for (size_t i = 0; i < mDevices.size(); i++) {
333 InputDevice* device = mDevices.valueAt(i);
334 mGlobalMetaState |= device->getMetaState();
335 }
336 } // release device registry reader lock
337 } // release state lock
338}
339
340int32_t InputReader::getGlobalMetaState() {
341 { // acquire state lock
342 AutoMutex _l(mStateLock);
343
344 return mGlobalMetaState;
345 } // release state lock
346}
347
348void InputReader::updateInputConfiguration() {
349 { // acquire state lock
350 AutoMutex _l(mStateLock);
351
352 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
353 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
354 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
355 { // acquire device registry reader lock
356 RWLock::AutoRLock _rl(mDeviceRegistryLock);
357
358 InputDeviceInfo deviceInfo;
359 for (size_t i = 0; i < mDevices.size(); i++) {
360 InputDevice* device = mDevices.valueAt(i);
361 device->getDeviceInfo(& deviceInfo);
362 uint32_t sources = deviceInfo.getSources();
363
364 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
365 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
366 }
367 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
368 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
369 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
370 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
371 }
372 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
373 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700374 }
375 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Brown46b9ac02010-04-22 18:58:52 -0700377
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 mInputConfiguration.touchScreen = touchScreenConfig;
379 mInputConfiguration.keyboard = keyboardConfig;
380 mInputConfiguration.navigation = navigationConfig;
381 } // release state lock
382}
383
Jeff Brownfe508922011-01-18 15:10:10 -0800384void InputReader::disableVirtualKeysUntil(nsecs_t time) {
385 mDisableVirtualKeysTimeout = time;
386}
387
388bool InputReader::shouldDropVirtualKey(nsecs_t now,
389 InputDevice* device, int32_t keyCode, int32_t scanCode) {
390 if (now < mDisableVirtualKeysTimeout) {
391 LOGI("Dropping virtual key from device %s because virtual keys are "
392 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
393 device->getName().string(),
394 (mDisableVirtualKeysTimeout - now) * 0.000001,
395 keyCode, scanCode);
396 return true;
397 } else {
398 return false;
399 }
400}
401
Jeff Brown6d0fec22010-07-23 21:28:06 -0700402void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
403 { // acquire state lock
404 AutoMutex _l(mStateLock);
405
406 *outConfiguration = mInputConfiguration;
407 } // release state lock
408}
409
410status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
411 { // acquire device registry reader lock
412 RWLock::AutoRLock _rl(mDeviceRegistryLock);
413
414 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
415 if (deviceIndex < 0) {
416 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700417 }
418
Jeff Brown6d0fec22010-07-23 21:28:06 -0700419 InputDevice* device = mDevices.valueAt(deviceIndex);
420 if (device->isIgnored()) {
421 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700422 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700423
424 device->getDeviceInfo(outDeviceInfo);
425 return OK;
426 } // release device registy reader lock
427}
428
429void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
430 outDeviceIds.clear();
431
432 { // acquire device registry reader lock
433 RWLock::AutoRLock _rl(mDeviceRegistryLock);
434
435 size_t numDevices = mDevices.size();
436 for (size_t i = 0; i < numDevices; i++) {
437 InputDevice* device = mDevices.valueAt(i);
438 if (! device->isIgnored()) {
439 outDeviceIds.add(device->getId());
440 }
441 }
442 } // release device registy reader lock
443}
444
445int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
446 int32_t keyCode) {
447 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
448}
449
450int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
451 int32_t scanCode) {
452 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
453}
454
455int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
456 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
457}
458
459int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
460 GetStateFunc getStateFunc) {
461 { // acquire device registry reader lock
462 RWLock::AutoRLock _rl(mDeviceRegistryLock);
463
464 int32_t result = AKEY_STATE_UNKNOWN;
465 if (deviceId >= 0) {
466 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
467 if (deviceIndex >= 0) {
468 InputDevice* device = mDevices.valueAt(deviceIndex);
469 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
470 result = (device->*getStateFunc)(sourceMask, code);
471 }
472 }
473 } else {
474 size_t numDevices = mDevices.size();
475 for (size_t i = 0; i < numDevices; i++) {
476 InputDevice* device = mDevices.valueAt(i);
477 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
478 result = (device->*getStateFunc)(sourceMask, code);
479 if (result >= AKEY_STATE_DOWN) {
480 return result;
481 }
482 }
483 }
484 }
485 return result;
486 } // release device registy reader lock
487}
488
489bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
490 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
491 memset(outFlags, 0, numCodes);
492 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
493}
494
495bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
496 const int32_t* keyCodes, uint8_t* outFlags) {
497 { // acquire device registry reader lock
498 RWLock::AutoRLock _rl(mDeviceRegistryLock);
499 bool result = false;
500 if (deviceId >= 0) {
501 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
502 if (deviceIndex >= 0) {
503 InputDevice* device = mDevices.valueAt(deviceIndex);
504 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
505 result = device->markSupportedKeyCodes(sourceMask,
506 numCodes, keyCodes, outFlags);
507 }
508 }
509 } else {
510 size_t numDevices = mDevices.size();
511 for (size_t i = 0; i < numDevices; i++) {
512 InputDevice* device = mDevices.valueAt(i);
513 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
514 result |= device->markSupportedKeyCodes(sourceMask,
515 numCodes, keyCodes, outFlags);
516 }
517 }
518 }
519 return result;
520 } // release device registy reader lock
521}
522
Jeff Brownb88102f2010-09-08 11:49:43 -0700523void InputReader::dump(String8& dump) {
Jeff Brownf2f48712010-10-01 17:46:21 -0700524 mEventHub->dump(dump);
525 dump.append("\n");
526
527 dump.append("Input Reader State:\n");
528
Jeff Brownef3d7e82010-09-30 14:33:04 -0700529 { // acquire device registry reader lock
530 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700531
Jeff Brownef3d7e82010-09-30 14:33:04 -0700532 for (size_t i = 0; i < mDevices.size(); i++) {
533 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700534 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700535 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700536}
537
Jeff Brown6d0fec22010-07-23 21:28:06 -0700538
539// --- InputReaderThread ---
540
541InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
542 Thread(/*canCallJava*/ true), mReader(reader) {
543}
544
545InputReaderThread::~InputReaderThread() {
546}
547
548bool InputReaderThread::threadLoop() {
549 mReader->loopOnce();
550 return true;
551}
552
553
554// --- InputDevice ---
555
556InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
557 mContext(context), mId(id), mName(name), mSources(0) {
558}
559
560InputDevice::~InputDevice() {
561 size_t numMappers = mMappers.size();
562 for (size_t i = 0; i < numMappers; i++) {
563 delete mMappers[i];
564 }
565 mMappers.clear();
566}
567
Jeff Brownef3d7e82010-09-30 14:33:04 -0700568void InputDevice::dump(String8& dump) {
569 InputDeviceInfo deviceInfo;
570 getDeviceInfo(& deviceInfo);
571
Jeff Brown90655042010-12-02 13:50:46 -0800572 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700573 deviceInfo.getName().string());
574 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
575 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800576
577 const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges();
578 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700579 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800580 for (size_t i = 0; i < ranges.size(); i++) {
581 int32_t axis = ranges.keyAt(i);
582 const char* label = getAxisLabel(axis);
583 char name[32];
584 if (label) {
585 strncpy(name, label, sizeof(name));
586 name[sizeof(name) - 1] = '\0';
587 } else {
588 snprintf(name, sizeof(name), "%d", axis);
589 }
590 const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
591 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
592 name, range.min, range.max, range.flat, range.fuzz);
593 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700594 }
595
596 size_t numMappers = mMappers.size();
597 for (size_t i = 0; i < numMappers; i++) {
598 InputMapper* mapper = mMappers[i];
599 mapper->dump(dump);
600 }
601}
602
Jeff Brown6d0fec22010-07-23 21:28:06 -0700603void InputDevice::addMapper(InputMapper* mapper) {
604 mMappers.add(mapper);
605}
606
607void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700608 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800609 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700610 }
611
Jeff Brown6d0fec22010-07-23 21:28:06 -0700612 mSources = 0;
613
614 size_t numMappers = mMappers.size();
615 for (size_t i = 0; i < numMappers; i++) {
616 InputMapper* mapper = mMappers[i];
617 mapper->configure();
618 mSources |= mapper->getSources();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700619 }
620}
621
Jeff Brown6d0fec22010-07-23 21:28:06 -0700622void InputDevice::reset() {
623 size_t numMappers = mMappers.size();
624 for (size_t i = 0; i < numMappers; i++) {
625 InputMapper* mapper = mMappers[i];
626 mapper->reset();
627 }
628}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700629
Jeff Brown6d0fec22010-07-23 21:28:06 -0700630void InputDevice::process(const RawEvent* rawEvent) {
631 size_t numMappers = mMappers.size();
632 for (size_t i = 0; i < numMappers; i++) {
633 InputMapper* mapper = mMappers[i];
634 mapper->process(rawEvent);
635 }
636}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700637
Jeff Brown6d0fec22010-07-23 21:28:06 -0700638void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
639 outDeviceInfo->initialize(mId, mName);
640
641 size_t numMappers = mMappers.size();
642 for (size_t i = 0; i < numMappers; i++) {
643 InputMapper* mapper = mMappers[i];
644 mapper->populateDeviceInfo(outDeviceInfo);
645 }
646}
647
648int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
649 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
650}
651
652int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
653 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
654}
655
656int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
657 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
658}
659
660int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
661 int32_t result = AKEY_STATE_UNKNOWN;
662 size_t numMappers = mMappers.size();
663 for (size_t i = 0; i < numMappers; i++) {
664 InputMapper* mapper = mMappers[i];
665 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
666 result = (mapper->*getStateFunc)(sourceMask, code);
667 if (result >= AKEY_STATE_DOWN) {
668 return result;
669 }
670 }
671 }
672 return result;
673}
674
675bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
676 const int32_t* keyCodes, uint8_t* outFlags) {
677 bool result = false;
678 size_t numMappers = mMappers.size();
679 for (size_t i = 0; i < numMappers; i++) {
680 InputMapper* mapper = mMappers[i];
681 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
682 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
683 }
684 }
685 return result;
686}
687
688int32_t InputDevice::getMetaState() {
689 int32_t result = 0;
690 size_t numMappers = mMappers.size();
691 for (size_t i = 0; i < numMappers; i++) {
692 InputMapper* mapper = mMappers[i];
693 result |= mapper->getMetaState();
694 }
695 return result;
696}
697
698
699// --- InputMapper ---
700
701InputMapper::InputMapper(InputDevice* device) :
702 mDevice(device), mContext(device->getContext()) {
703}
704
705InputMapper::~InputMapper() {
706}
707
708void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
709 info->addSource(getSources());
710}
711
Jeff Brownef3d7e82010-09-30 14:33:04 -0700712void InputMapper::dump(String8& dump) {
713}
714
Jeff Brown6d0fec22010-07-23 21:28:06 -0700715void InputMapper::configure() {
716}
717
718void InputMapper::reset() {
719}
720
721int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
722 return AKEY_STATE_UNKNOWN;
723}
724
725int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
726 return AKEY_STATE_UNKNOWN;
727}
728
729int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
730 return AKEY_STATE_UNKNOWN;
731}
732
733bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
734 const int32_t* keyCodes, uint8_t* outFlags) {
735 return false;
736}
737
738int32_t InputMapper::getMetaState() {
739 return 0;
740}
741
Jeff Browncb1404e2011-01-15 18:14:15 -0800742void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
743 const RawAbsoluteAxisInfo& axis, const char* name) {
744 if (axis.valid) {
745 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
746 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
747 } else {
748 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
749 }
750}
751
Jeff Brown6d0fec22010-07-23 21:28:06 -0700752
753// --- SwitchInputMapper ---
754
755SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
756 InputMapper(device) {
757}
758
759SwitchInputMapper::~SwitchInputMapper() {
760}
761
762uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800763 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700764}
765
766void SwitchInputMapper::process(const RawEvent* rawEvent) {
767 switch (rawEvent->type) {
768 case EV_SW:
769 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
770 break;
771 }
772}
773
774void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700775 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700776}
777
778int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
779 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
780}
781
782
783// --- KeyboardInputMapper ---
784
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800785KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700786 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800787 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700788 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700789 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700790}
791
792KeyboardInputMapper::~KeyboardInputMapper() {
793}
794
Jeff Brown6328cdc2010-07-29 18:18:33 -0700795void KeyboardInputMapper::initializeLocked() {
796 mLocked.metaState = AMETA_NONE;
797 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700798}
799
800uint32_t KeyboardInputMapper::getSources() {
801 return mSources;
802}
803
804void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
805 InputMapper::populateDeviceInfo(info);
806
807 info->setKeyboardType(mKeyboardType);
808}
809
Jeff Brownef3d7e82010-09-30 14:33:04 -0700810void KeyboardInputMapper::dump(String8& dump) {
811 { // acquire lock
812 AutoMutex _l(mLock);
813 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800814 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700815 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
816 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
817 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
818 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
819 } // release lock
820}
821
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800822
823void KeyboardInputMapper::configure() {
824 InputMapper::configure();
825
826 // Configure basic parameters.
827 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800828
829 // Reset LEDs.
830 {
831 AutoMutex _l(mLock);
832 resetLedStateLocked();
833 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800834}
835
836void KeyboardInputMapper::configureParameters() {
837 mParameters.orientationAware = false;
838 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
839 mParameters.orientationAware);
840
841 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
842}
843
844void KeyboardInputMapper::dumpParameters(String8& dump) {
845 dump.append(INDENT3 "Parameters:\n");
846 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
847 mParameters.associatedDisplayId);
848 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
849 toString(mParameters.orientationAware));
850}
851
Jeff Brown6d0fec22010-07-23 21:28:06 -0700852void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700853 for (;;) {
854 int32_t keyCode, scanCode;
855 { // acquire lock
856 AutoMutex _l(mLock);
857
858 // Synthesize key up event on reset if keys are currently down.
859 if (mLocked.keyDowns.isEmpty()) {
860 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800861 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700862 break; // done
863 }
864
865 const KeyDown& keyDown = mLocked.keyDowns.top();
866 keyCode = keyDown.keyCode;
867 scanCode = keyDown.scanCode;
868 } // release lock
869
Jeff Brown6d0fec22010-07-23 21:28:06 -0700870 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700871 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700872 }
873
874 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700875 getContext()->updateGlobalMetaState();
876}
877
878void KeyboardInputMapper::process(const RawEvent* rawEvent) {
879 switch (rawEvent->type) {
880 case EV_KEY: {
881 int32_t scanCode = rawEvent->scanCode;
882 if (isKeyboardOrGamepadKey(scanCode)) {
883 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
884 rawEvent->flags);
885 }
886 break;
887 }
888 }
889}
890
891bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
892 return scanCode < BTN_MOUSE
893 || scanCode >= KEY_OK
Jeff Browncb1404e2011-01-15 18:14:15 -0800894 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700895}
896
Jeff Brown6328cdc2010-07-29 18:18:33 -0700897void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
898 int32_t scanCode, uint32_t policyFlags) {
899 int32_t newMetaState;
900 nsecs_t downTime;
901 bool metaStateChanged = false;
902
903 { // acquire lock
904 AutoMutex _l(mLock);
905
906 if (down) {
907 // Rotate key codes according to orientation if needed.
908 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800909 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700910 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800911 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
912 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800913 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700914 }
915
916 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700917 }
918
Jeff Brown6328cdc2010-07-29 18:18:33 -0700919 // Add key down.
920 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
921 if (keyDownIndex >= 0) {
922 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800923 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700924 } else {
925 // key down
Jeff Brownfe508922011-01-18 15:10:10 -0800926 if ((policyFlags & POLICY_FLAG_VIRTUAL)
927 && mContext->shouldDropVirtualKey(when,
928 getDevice(), keyCode, scanCode)) {
929 return;
930 }
931
Jeff Brown6328cdc2010-07-29 18:18:33 -0700932 mLocked.keyDowns.push();
933 KeyDown& keyDown = mLocked.keyDowns.editTop();
934 keyDown.keyCode = keyCode;
935 keyDown.scanCode = scanCode;
936 }
937
938 mLocked.downTime = when;
939 } else {
940 // Remove key down.
941 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
942 if (keyDownIndex >= 0) {
943 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800944 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700945 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
946 } else {
947 // key was not actually down
948 LOGI("Dropping key up from device %s because the key was not down. "
949 "keyCode=%d, scanCode=%d",
950 getDeviceName().string(), keyCode, scanCode);
951 return;
952 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700953 }
954
Jeff Brown6328cdc2010-07-29 18:18:33 -0700955 int32_t oldMetaState = mLocked.metaState;
956 newMetaState = updateMetaState(keyCode, down, oldMetaState);
957 if (oldMetaState != newMetaState) {
958 mLocked.metaState = newMetaState;
959 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -0700960 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700961 }
Jeff Brownfd035822010-06-30 16:10:35 -0700962
Jeff Brown6328cdc2010-07-29 18:18:33 -0700963 downTime = mLocked.downTime;
964 } // release lock
965
966 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700967 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700968 }
969
Jeff Brown497a92c2010-09-12 17:55:08 -0700970 if (policyFlags & POLICY_FLAG_FUNCTION) {
971 newMetaState |= AMETA_FUNCTION_ON;
972 }
Jeff Brown83c09682010-12-23 17:50:18 -0800973 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -0700974 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
975 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700976}
977
Jeff Brown6328cdc2010-07-29 18:18:33 -0700978ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
979 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700980 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700981 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700982 return i;
983 }
984 }
985 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700986}
987
Jeff Brown6d0fec22010-07-23 21:28:06 -0700988int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
989 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
990}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700991
Jeff Brown6d0fec22010-07-23 21:28:06 -0700992int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
993 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
994}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700995
Jeff Brown6d0fec22010-07-23 21:28:06 -0700996bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
997 const int32_t* keyCodes, uint8_t* outFlags) {
998 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
999}
1000
1001int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001002 { // acquire lock
1003 AutoMutex _l(mLock);
1004 return mLocked.metaState;
1005 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001006}
1007
Jeff Brown49ed71d2010-12-06 17:13:33 -08001008void KeyboardInputMapper::resetLedStateLocked() {
1009 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1010 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1011 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1012
1013 updateLedStateLocked(true);
1014}
1015
1016void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1017 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1018 ledState.on = false;
1019}
1020
Jeff Brown497a92c2010-09-12 17:55:08 -07001021void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1022 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001023 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001024 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001025 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001026 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001027 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001028}
1029
1030void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1031 int32_t led, int32_t modifier, bool reset) {
1032 if (ledState.avail) {
1033 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001034 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001035 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1036 ledState.on = desiredState;
1037 }
1038 }
1039}
1040
Jeff Brown6d0fec22010-07-23 21:28:06 -07001041
Jeff Brown83c09682010-12-23 17:50:18 -08001042// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001043
Jeff Brown83c09682010-12-23 17:50:18 -08001044CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001045 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001046 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001047}
1048
Jeff Brown83c09682010-12-23 17:50:18 -08001049CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001050}
1051
Jeff Brown83c09682010-12-23 17:50:18 -08001052uint32_t CursorInputMapper::getSources() {
1053 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001054}
1055
Jeff Brown83c09682010-12-23 17:50:18 -08001056void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001057 InputMapper::populateDeviceInfo(info);
1058
Jeff Brown83c09682010-12-23 17:50:18 -08001059 if (mParameters.mode == Parameters::MODE_POINTER) {
1060 float minX, minY, maxX, maxY;
1061 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001062 info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
1063 info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001064 }
1065 } else {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001066 info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
1067 info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001068 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001069 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
1070
1071 if (mHaveVWheel) {
1072 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1073 }
1074 if (mHaveHWheel) {
1075 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1076 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001077}
1078
Jeff Brown83c09682010-12-23 17:50:18 -08001079void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001080 { // acquire lock
1081 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001082 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001083 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001084 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1085 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001086 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1087 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001088 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1089 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1090 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1091 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001092 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1093 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1094 } // release lock
1095}
1096
Jeff Brown83c09682010-12-23 17:50:18 -08001097void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001098 InputMapper::configure();
1099
1100 // Configure basic parameters.
1101 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001102
1103 // Configure device mode.
1104 switch (mParameters.mode) {
1105 case Parameters::MODE_POINTER:
1106 mSources = AINPUT_SOURCE_MOUSE;
1107 mXPrecision = 1.0f;
1108 mYPrecision = 1.0f;
1109 mXScale = 1.0f;
1110 mYScale = 1.0f;
1111 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1112 break;
1113 case Parameters::MODE_NAVIGATION:
1114 mSources = AINPUT_SOURCE_TRACKBALL;
1115 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1116 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1117 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1118 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1119 break;
1120 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001121
1122 mVWheelScale = 1.0f;
1123 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001124
1125 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1126 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001127}
1128
Jeff Brown83c09682010-12-23 17:50:18 -08001129void CursorInputMapper::configureParameters() {
1130 mParameters.mode = Parameters::MODE_POINTER;
1131 String8 cursorModeString;
1132 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1133 if (cursorModeString == "navigation") {
1134 mParameters.mode = Parameters::MODE_NAVIGATION;
1135 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1136 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1137 }
1138 }
1139
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001140 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001141 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001142 mParameters.orientationAware);
1143
Jeff Brown83c09682010-12-23 17:50:18 -08001144 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1145 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001146}
1147
Jeff Brown83c09682010-12-23 17:50:18 -08001148void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001149 dump.append(INDENT3 "Parameters:\n");
1150 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1151 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001152
1153 switch (mParameters.mode) {
1154 case Parameters::MODE_POINTER:
1155 dump.append(INDENT4 "Mode: pointer\n");
1156 break;
1157 case Parameters::MODE_NAVIGATION:
1158 dump.append(INDENT4 "Mode: navigation\n");
1159 break;
1160 default:
1161 assert(false);
1162 }
1163
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001164 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1165 toString(mParameters.orientationAware));
1166}
1167
Jeff Brown83c09682010-12-23 17:50:18 -08001168void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001169 mAccumulator.clear();
1170
Jeff Brown6328cdc2010-07-29 18:18:33 -07001171 mLocked.down = false;
1172 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001173}
1174
Jeff Brown83c09682010-12-23 17:50:18 -08001175void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001176 for (;;) {
1177 { // acquire lock
1178 AutoMutex _l(mLock);
1179
1180 if (! mLocked.down) {
1181 initializeLocked();
1182 break; // done
1183 }
1184 } // release lock
1185
Jeff Brown83c09682010-12-23 17:50:18 -08001186 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001187 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001188 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001189 mAccumulator.btnMouse = false;
1190 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001191 }
1192
Jeff Brown6d0fec22010-07-23 21:28:06 -07001193 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001194}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001195
Jeff Brown83c09682010-12-23 17:50:18 -08001196void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001197 switch (rawEvent->type) {
1198 case EV_KEY:
1199 switch (rawEvent->scanCode) {
1200 case BTN_MOUSE:
1201 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1202 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001203 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1204 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001205 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001206 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001207 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001208 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001209
Jeff Brown6d0fec22010-07-23 21:28:06 -07001210 case EV_REL:
1211 switch (rawEvent->scanCode) {
1212 case REL_X:
1213 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1214 mAccumulator.relX = rawEvent->value;
1215 break;
1216 case REL_Y:
1217 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1218 mAccumulator.relY = rawEvent->value;
1219 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001220 case REL_WHEEL:
1221 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1222 mAccumulator.relWheel = rawEvent->value;
1223 break;
1224 case REL_HWHEEL:
1225 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1226 mAccumulator.relHWheel = rawEvent->value;
1227 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001228 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001229 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001230
Jeff Brown6d0fec22010-07-23 21:28:06 -07001231 case EV_SYN:
1232 switch (rawEvent->scanCode) {
1233 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001234 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001235 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001236 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001237 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001238 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001239}
1240
Jeff Brown83c09682010-12-23 17:50:18 -08001241void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001242 uint32_t fields = mAccumulator.fields;
1243 if (fields == 0) {
1244 return; // no new state changes, so nothing to do
1245 }
1246
Jeff Brown6328cdc2010-07-29 18:18:33 -07001247 int motionEventAction;
1248 PointerCoords pointerCoords;
1249 nsecs_t downTime;
1250 { // acquire lock
1251 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001252
Jeff Brown6328cdc2010-07-29 18:18:33 -07001253 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1254
1255 if (downChanged) {
1256 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001257 if (!mLocked.down) {
1258 mLocked.down = true;
1259 mLocked.downTime = when;
1260 } else {
1261 downChanged = false;
1262 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001263 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001264 if (mLocked.down) {
1265 mLocked.down = false;
1266 } else {
1267 downChanged = false;
1268 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001269 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001270 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001271
Jeff Brown6328cdc2010-07-29 18:18:33 -07001272 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001273 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1274 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001275
Jeff Brown6328cdc2010-07-29 18:18:33 -07001276 if (downChanged) {
1277 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browncc0c1592011-02-19 05:07:28 -08001278 } else if (mLocked.down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001279 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001280 } else {
1281 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001282 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001283
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001284 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001285 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001286 // Rotate motion based on display orientation if needed.
1287 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1288 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001289 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1290 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001291 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001292 }
1293
1294 float temp;
1295 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001296 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001297 temp = deltaX;
1298 deltaX = deltaY;
1299 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001300 break;
1301
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001302 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001303 deltaX = -deltaX;
1304 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001305 break;
1306
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001307 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001308 temp = deltaX;
1309 deltaX = -deltaY;
1310 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001311 break;
1312 }
1313 }
Jeff Brown83c09682010-12-23 17:50:18 -08001314
Jeff Brown91c69ab2011-02-14 17:03:18 -08001315 pointerCoords.clear();
1316
Jeff Brown83c09682010-12-23 17:50:18 -08001317 if (mPointerController != NULL) {
1318 mPointerController->move(deltaX, deltaY);
1319 if (downChanged) {
1320 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1321 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08001322 float x, y;
1323 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001324 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1325 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown83c09682010-12-23 17:50:18 -08001326 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001327 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1328 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001329 }
1330
Jeff Brownebbd5d12011-02-17 13:01:34 -08001331 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001332
1333 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1334 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, mAccumulator.relWheel);
1335 }
1336 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1337 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, mAccumulator.relHWheel);
1338 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001339 } // release lock
1340
Jeff Brown6d0fec22010-07-23 21:28:06 -07001341 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001342 int32_t pointerId = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001343 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
Jeff Brown85a31762010-09-01 17:01:00 -07001344 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001345 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1346
1347 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001348}
1349
Jeff Brown83c09682010-12-23 17:50:18 -08001350int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001351 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1352 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1353 } else {
1354 return AKEY_STATE_UNKNOWN;
1355 }
1356}
1357
Jeff Brown6d0fec22010-07-23 21:28:06 -07001358
1359// --- TouchInputMapper ---
1360
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001361TouchInputMapper::TouchInputMapper(InputDevice* device) :
1362 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001363 mLocked.surfaceOrientation = -1;
1364 mLocked.surfaceWidth = -1;
1365 mLocked.surfaceHeight = -1;
1366
1367 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001368}
1369
1370TouchInputMapper::~TouchInputMapper() {
1371}
1372
1373uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001374 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001375}
1376
1377void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1378 InputMapper::populateDeviceInfo(info);
1379
Jeff Brown6328cdc2010-07-29 18:18:33 -07001380 { // acquire lock
1381 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001382
Jeff Brown6328cdc2010-07-29 18:18:33 -07001383 // Ensure surface information is up to date so that orientation changes are
1384 // noticed immediately.
1385 configureSurfaceLocked();
1386
Jeff Brown6f2fba42011-02-19 01:08:02 -08001387 info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1388 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001389
1390 if (mLocked.orientedRanges.havePressure) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001391 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown8d608662010-08-30 03:02:23 -07001392 mLocked.orientedRanges.pressure);
1393 }
1394
1395 if (mLocked.orientedRanges.haveSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001396 info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown8d608662010-08-30 03:02:23 -07001397 mLocked.orientedRanges.size);
1398 }
1399
Jeff Brownc6d282b2010-10-14 21:42:15 -07001400 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001401 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001402 mLocked.orientedRanges.touchMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001403 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001404 mLocked.orientedRanges.touchMinor);
1405 }
1406
Jeff Brownc6d282b2010-10-14 21:42:15 -07001407 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001408 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001409 mLocked.orientedRanges.toolMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001410 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001411 mLocked.orientedRanges.toolMinor);
1412 }
1413
1414 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001415 info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown8d608662010-08-30 03:02:23 -07001416 mLocked.orientedRanges.orientation);
1417 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001418 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001419}
1420
Jeff Brownef3d7e82010-09-30 14:33:04 -07001421void TouchInputMapper::dump(String8& dump) {
1422 { // acquire lock
1423 AutoMutex _l(mLock);
1424 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001425 dumpParameters(dump);
1426 dumpVirtualKeysLocked(dump);
1427 dumpRawAxes(dump);
1428 dumpCalibration(dump);
1429 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001430 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001431 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1432 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1433 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1434 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1435 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1436 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1437 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1438 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1439 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1440 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1441 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1442 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1443 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1444 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001445 } // release lock
1446}
1447
Jeff Brown6328cdc2010-07-29 18:18:33 -07001448void TouchInputMapper::initializeLocked() {
1449 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001450 mLastTouch.clear();
1451 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001452
1453 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1454 mAveragingTouchFilter.historyStart[i] = 0;
1455 mAveragingTouchFilter.historyEnd[i] = 0;
1456 }
1457
1458 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001459
1460 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001461
1462 mLocked.orientedRanges.havePressure = false;
1463 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001464 mLocked.orientedRanges.haveTouchSize = false;
1465 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001466 mLocked.orientedRanges.haveOrientation = false;
1467}
1468
Jeff Brown6d0fec22010-07-23 21:28:06 -07001469void TouchInputMapper::configure() {
1470 InputMapper::configure();
1471
1472 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001473 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001474
Jeff Brown83c09682010-12-23 17:50:18 -08001475 // Configure sources.
1476 switch (mParameters.deviceType) {
1477 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1478 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1479 break;
1480 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1481 mSources = AINPUT_SOURCE_TOUCHPAD;
1482 break;
1483 default:
1484 assert(false);
1485 }
1486
Jeff Brown6d0fec22010-07-23 21:28:06 -07001487 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001488 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001489
1490 // Prepare input device calibration.
1491 parseCalibration();
1492 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001493
Jeff Brown6328cdc2010-07-29 18:18:33 -07001494 { // acquire lock
1495 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001496
Jeff Brown8d608662010-08-30 03:02:23 -07001497 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001498 configureSurfaceLocked();
1499 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001500}
1501
Jeff Brown8d608662010-08-30 03:02:23 -07001502void TouchInputMapper::configureParameters() {
1503 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1504 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1505 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001506 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001507
1508 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001509 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001510 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1511 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001512 if (deviceTypeString == "touchScreen") {
1513 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1514 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001515 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1516 }
1517 }
1518 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1519
1520 mParameters.orientationAware = isTouchScreen;
1521 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1522 mParameters.orientationAware);
1523
1524 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001525}
1526
Jeff Brownef3d7e82010-09-30 14:33:04 -07001527void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001528 dump.append(INDENT3 "Parameters:\n");
1529
1530 switch (mParameters.deviceType) {
1531 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1532 dump.append(INDENT4 "DeviceType: touchScreen\n");
1533 break;
1534 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1535 dump.append(INDENT4 "DeviceType: touchPad\n");
1536 break;
1537 default:
1538 assert(false);
1539 }
1540
1541 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1542 mParameters.associatedDisplayId);
1543 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1544 toString(mParameters.orientationAware));
1545
1546 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001547 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001548 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001549 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001550 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001551 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001552}
1553
Jeff Brown8d608662010-08-30 03:02:23 -07001554void TouchInputMapper::configureRawAxes() {
1555 mRawAxes.x.clear();
1556 mRawAxes.y.clear();
1557 mRawAxes.pressure.clear();
1558 mRawAxes.touchMajor.clear();
1559 mRawAxes.touchMinor.clear();
1560 mRawAxes.toolMajor.clear();
1561 mRawAxes.toolMinor.clear();
1562 mRawAxes.orientation.clear();
1563}
1564
Jeff Brownef3d7e82010-09-30 14:33:04 -07001565void TouchInputMapper::dumpRawAxes(String8& dump) {
1566 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001567 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1568 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1569 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1570 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1571 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1572 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1573 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1574 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001575}
1576
Jeff Brown6328cdc2010-07-29 18:18:33 -07001577bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001578 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001579 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001580 int32_t width = mRawAxes.x.getRange();
1581 int32_t height = mRawAxes.y.getRange();
1582
1583 if (mParameters.associatedDisplayId >= 0) {
1584 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1585 bool wantOrientation = mParameters.orientationAware;
1586
Jeff Brown6328cdc2010-07-29 18:18:33 -07001587 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001588 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1589 wantSize ? &width : NULL, wantSize ? &height : NULL,
1590 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001591 return false;
1592 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001593 }
1594
Jeff Brown6328cdc2010-07-29 18:18:33 -07001595 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001596 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001597 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001598 }
1599
Jeff Brown6328cdc2010-07-29 18:18:33 -07001600 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001601 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001602 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001603 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001604
Jeff Brown6328cdc2010-07-29 18:18:33 -07001605 mLocked.surfaceWidth = width;
1606 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001607
Jeff Brown8d608662010-08-30 03:02:23 -07001608 // Configure X and Y factors.
1609 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001610 mLocked.xOrigin = mCalibration.haveXOrigin
1611 ? mCalibration.xOrigin
1612 : mRawAxes.x.minValue;
1613 mLocked.yOrigin = mCalibration.haveYOrigin
1614 ? mCalibration.yOrigin
1615 : mRawAxes.y.minValue;
1616 mLocked.xScale = mCalibration.haveXScale
1617 ? mCalibration.xScale
1618 : float(width) / mRawAxes.x.getRange();
1619 mLocked.yScale = mCalibration.haveYScale
1620 ? mCalibration.yScale
1621 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001622 mLocked.xPrecision = 1.0f / mLocked.xScale;
1623 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001624
Jeff Brown6328cdc2010-07-29 18:18:33 -07001625 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001626 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001627 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001628 mLocked.xOrigin = 0;
1629 mLocked.yOrigin = 0;
1630 mLocked.xScale = 1.0f;
1631 mLocked.yScale = 1.0f;
1632 mLocked.xPrecision = 1.0f;
1633 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001634 }
1635
Jeff Brown8d608662010-08-30 03:02:23 -07001636 // Scale factor for terms that are not oriented in a particular axis.
1637 // If the pixels are square then xScale == yScale otherwise we fake it
1638 // by choosing an average.
1639 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001640
Jeff Brown8d608662010-08-30 03:02:23 -07001641 // Size of diagonal axis.
1642 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001643
Jeff Brown8d608662010-08-30 03:02:23 -07001644 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001645 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1646 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001647 mLocked.orientedRanges.touchMajor.min = 0;
1648 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1649 mLocked.orientedRanges.touchMajor.flat = 0;
1650 mLocked.orientedRanges.touchMajor.fuzz = 0;
1651 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1652 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001653
Jeff Brown8d608662010-08-30 03:02:23 -07001654 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001655 mLocked.toolSizeLinearScale = 0;
1656 mLocked.toolSizeLinearBias = 0;
1657 mLocked.toolSizeAreaScale = 0;
1658 mLocked.toolSizeAreaBias = 0;
1659 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1660 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1661 if (mCalibration.haveToolSizeLinearScale) {
1662 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001663 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001664 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001665 / mRawAxes.toolMajor.maxValue;
1666 }
1667
Jeff Brownc6d282b2010-10-14 21:42:15 -07001668 if (mCalibration.haveToolSizeLinearBias) {
1669 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1670 }
1671 } else if (mCalibration.toolSizeCalibration ==
1672 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1673 if (mCalibration.haveToolSizeLinearScale) {
1674 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1675 } else {
1676 mLocked.toolSizeLinearScale = min(width, height);
1677 }
1678
1679 if (mCalibration.haveToolSizeLinearBias) {
1680 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1681 }
1682
1683 if (mCalibration.haveToolSizeAreaScale) {
1684 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1685 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1686 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1687 }
1688
1689 if (mCalibration.haveToolSizeAreaBias) {
1690 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001691 }
1692 }
1693
Jeff Brownc6d282b2010-10-14 21:42:15 -07001694 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001695 mLocked.orientedRanges.toolMajor.min = 0;
1696 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1697 mLocked.orientedRanges.toolMajor.flat = 0;
1698 mLocked.orientedRanges.toolMajor.fuzz = 0;
1699 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1700 }
1701
1702 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001703 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001704 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1705 RawAbsoluteAxisInfo rawPressureAxis;
1706 switch (mCalibration.pressureSource) {
1707 case Calibration::PRESSURE_SOURCE_PRESSURE:
1708 rawPressureAxis = mRawAxes.pressure;
1709 break;
1710 case Calibration::PRESSURE_SOURCE_TOUCH:
1711 rawPressureAxis = mRawAxes.touchMajor;
1712 break;
1713 default:
1714 rawPressureAxis.clear();
1715 }
1716
Jeff Brown8d608662010-08-30 03:02:23 -07001717 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1718 || mCalibration.pressureCalibration
1719 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1720 if (mCalibration.havePressureScale) {
1721 mLocked.pressureScale = mCalibration.pressureScale;
1722 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1723 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1724 }
1725 }
1726
1727 mLocked.orientedRanges.havePressure = true;
1728 mLocked.orientedRanges.pressure.min = 0;
1729 mLocked.orientedRanges.pressure.max = 1.0;
1730 mLocked.orientedRanges.pressure.flat = 0;
1731 mLocked.orientedRanges.pressure.fuzz = 0;
1732 }
1733
1734 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001735 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001736 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001737 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1738 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1739 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1740 }
1741 }
1742
1743 mLocked.orientedRanges.haveSize = true;
1744 mLocked.orientedRanges.size.min = 0;
1745 mLocked.orientedRanges.size.max = 1.0;
1746 mLocked.orientedRanges.size.flat = 0;
1747 mLocked.orientedRanges.size.fuzz = 0;
1748 }
1749
1750 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001751 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001752 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001753 if (mCalibration.orientationCalibration
1754 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1755 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1756 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1757 }
1758 }
1759
1760 mLocked.orientedRanges.orientation.min = - M_PI_2;
1761 mLocked.orientedRanges.orientation.max = M_PI_2;
1762 mLocked.orientedRanges.orientation.flat = 0;
1763 mLocked.orientedRanges.orientation.fuzz = 0;
1764 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001765 }
1766
1767 if (orientationChanged || sizeChanged) {
1768 // Compute oriented surface dimensions, precision, and scales.
1769 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001770 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001771 case DISPLAY_ORIENTATION_90:
1772 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001773 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1774 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1775 mLocked.orientedXPrecision = mLocked.yPrecision;
1776 mLocked.orientedYPrecision = mLocked.xPrecision;
1777 orientedXScale = mLocked.yScale;
1778 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001779 break;
1780 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001781 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1782 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1783 mLocked.orientedXPrecision = mLocked.xPrecision;
1784 mLocked.orientedYPrecision = mLocked.yPrecision;
1785 orientedXScale = mLocked.xScale;
1786 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001787 break;
1788 }
1789
1790 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001791 mLocked.orientedRanges.x.min = 0;
1792 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1793 mLocked.orientedRanges.x.flat = 0;
1794 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001795
Jeff Brown6328cdc2010-07-29 18:18:33 -07001796 mLocked.orientedRanges.y.min = 0;
1797 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1798 mLocked.orientedRanges.y.flat = 0;
1799 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001800 }
1801
1802 return true;
1803}
1804
Jeff Brownef3d7e82010-09-30 14:33:04 -07001805void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1806 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1807 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1808 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001809}
1810
Jeff Brown6328cdc2010-07-29 18:18:33 -07001811void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001812 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001813
Jeff Brown8d608662010-08-30 03:02:23 -07001814 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001815 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001816
Jeff Brown6328cdc2010-07-29 18:18:33 -07001817 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001818
Jeff Brown6328cdc2010-07-29 18:18:33 -07001819 if (virtualKeyDefinitions.size() == 0) {
1820 return;
1821 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001822
Jeff Brown6328cdc2010-07-29 18:18:33 -07001823 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1824
Jeff Brown8d608662010-08-30 03:02:23 -07001825 int32_t touchScreenLeft = mRawAxes.x.minValue;
1826 int32_t touchScreenTop = mRawAxes.y.minValue;
1827 int32_t touchScreenWidth = mRawAxes.x.getRange();
1828 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001829
1830 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001831 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001832 virtualKeyDefinitions[i];
1833
1834 mLocked.virtualKeys.add();
1835 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1836
1837 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1838 int32_t keyCode;
1839 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001840 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001841 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001842 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1843 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001844 mLocked.virtualKeys.pop(); // drop the key
1845 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001846 }
1847
Jeff Brown6328cdc2010-07-29 18:18:33 -07001848 virtualKey.keyCode = keyCode;
1849 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001850
Jeff Brown6328cdc2010-07-29 18:18:33 -07001851 // convert the key definition's display coordinates into touch coordinates for a hit box
1852 int32_t halfWidth = virtualKeyDefinition.width / 2;
1853 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001854
Jeff Brown6328cdc2010-07-29 18:18:33 -07001855 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1856 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1857 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1858 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1859 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1860 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1861 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1862 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001863
Jeff Brownef3d7e82010-09-30 14:33:04 -07001864 }
1865}
1866
1867void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1868 if (!mLocked.virtualKeys.isEmpty()) {
1869 dump.append(INDENT3 "Virtual Keys:\n");
1870
1871 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1872 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1873 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1874 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1875 i, virtualKey.scanCode, virtualKey.keyCode,
1876 virtualKey.hitLeft, virtualKey.hitRight,
1877 virtualKey.hitTop, virtualKey.hitBottom);
1878 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001879 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001880}
1881
Jeff Brown8d608662010-08-30 03:02:23 -07001882void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001883 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001884 Calibration& out = mCalibration;
1885
Jeff Brown511ee5f2010-10-18 13:32:20 -07001886 // Position
1887 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1888 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1889 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1890 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1891
Jeff Brownc6d282b2010-10-14 21:42:15 -07001892 // Touch Size
1893 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1894 String8 touchSizeCalibrationString;
1895 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1896 if (touchSizeCalibrationString == "none") {
1897 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1898 } else if (touchSizeCalibrationString == "geometric") {
1899 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1900 } else if (touchSizeCalibrationString == "pressure") {
1901 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1902 } else if (touchSizeCalibrationString != "default") {
1903 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1904 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001905 }
1906 }
1907
Jeff Brownc6d282b2010-10-14 21:42:15 -07001908 // Tool Size
1909 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1910 String8 toolSizeCalibrationString;
1911 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1912 if (toolSizeCalibrationString == "none") {
1913 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1914 } else if (toolSizeCalibrationString == "geometric") {
1915 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1916 } else if (toolSizeCalibrationString == "linear") {
1917 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1918 } else if (toolSizeCalibrationString == "area") {
1919 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1920 } else if (toolSizeCalibrationString != "default") {
1921 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1922 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001923 }
1924 }
1925
Jeff Brownc6d282b2010-10-14 21:42:15 -07001926 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1927 out.toolSizeLinearScale);
1928 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1929 out.toolSizeLinearBias);
1930 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1931 out.toolSizeAreaScale);
1932 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1933 out.toolSizeAreaBias);
1934 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1935 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07001936
1937 // Pressure
1938 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1939 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001940 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001941 if (pressureCalibrationString == "none") {
1942 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1943 } else if (pressureCalibrationString == "physical") {
1944 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1945 } else if (pressureCalibrationString == "amplitude") {
1946 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1947 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001948 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001949 pressureCalibrationString.string());
1950 }
1951 }
1952
1953 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1954 String8 pressureSourceString;
1955 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1956 if (pressureSourceString == "pressure") {
1957 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1958 } else if (pressureSourceString == "touch") {
1959 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1960 } else if (pressureSourceString != "default") {
1961 LOGW("Invalid value for touch.pressure.source: '%s'",
1962 pressureSourceString.string());
1963 }
1964 }
1965
1966 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1967 out.pressureScale);
1968
1969 // Size
1970 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1971 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001972 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001973 if (sizeCalibrationString == "none") {
1974 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1975 } else if (sizeCalibrationString == "normalized") {
1976 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1977 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001978 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001979 sizeCalibrationString.string());
1980 }
1981 }
1982
1983 // Orientation
1984 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1985 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001986 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001987 if (orientationCalibrationString == "none") {
1988 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1989 } else if (orientationCalibrationString == "interpolated") {
1990 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08001991 } else if (orientationCalibrationString == "vector") {
1992 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001993 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001994 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001995 orientationCalibrationString.string());
1996 }
1997 }
1998}
1999
2000void TouchInputMapper::resolveCalibration() {
2001 // Pressure
2002 switch (mCalibration.pressureSource) {
2003 case Calibration::PRESSURE_SOURCE_DEFAULT:
2004 if (mRawAxes.pressure.valid) {
2005 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2006 } else if (mRawAxes.touchMajor.valid) {
2007 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2008 }
2009 break;
2010
2011 case Calibration::PRESSURE_SOURCE_PRESSURE:
2012 if (! mRawAxes.pressure.valid) {
2013 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2014 "the pressure axis is not available.");
2015 }
2016 break;
2017
2018 case Calibration::PRESSURE_SOURCE_TOUCH:
2019 if (! mRawAxes.touchMajor.valid) {
2020 LOGW("Calibration property touch.pressure.source is 'touch' but "
2021 "the touchMajor axis is not available.");
2022 }
2023 break;
2024
2025 default:
2026 break;
2027 }
2028
2029 switch (mCalibration.pressureCalibration) {
2030 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2031 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2032 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2033 } else {
2034 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2035 }
2036 break;
2037
2038 default:
2039 break;
2040 }
2041
Jeff Brownc6d282b2010-10-14 21:42:15 -07002042 // Tool Size
2043 switch (mCalibration.toolSizeCalibration) {
2044 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002045 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002046 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002047 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002048 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002049 }
2050 break;
2051
2052 default:
2053 break;
2054 }
2055
Jeff Brownc6d282b2010-10-14 21:42:15 -07002056 // Touch Size
2057 switch (mCalibration.touchSizeCalibration) {
2058 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002059 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002060 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2061 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002062 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002063 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002064 }
2065 break;
2066
2067 default:
2068 break;
2069 }
2070
2071 // Size
2072 switch (mCalibration.sizeCalibration) {
2073 case Calibration::SIZE_CALIBRATION_DEFAULT:
2074 if (mRawAxes.toolMajor.valid) {
2075 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2076 } else {
2077 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2078 }
2079 break;
2080
2081 default:
2082 break;
2083 }
2084
2085 // Orientation
2086 switch (mCalibration.orientationCalibration) {
2087 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2088 if (mRawAxes.orientation.valid) {
2089 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2090 } else {
2091 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2092 }
2093 break;
2094
2095 default:
2096 break;
2097 }
2098}
2099
Jeff Brownef3d7e82010-09-30 14:33:04 -07002100void TouchInputMapper::dumpCalibration(String8& dump) {
2101 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002102
Jeff Brown511ee5f2010-10-18 13:32:20 -07002103 // Position
2104 if (mCalibration.haveXOrigin) {
2105 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2106 }
2107 if (mCalibration.haveYOrigin) {
2108 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2109 }
2110 if (mCalibration.haveXScale) {
2111 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2112 }
2113 if (mCalibration.haveYScale) {
2114 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2115 }
2116
Jeff Brownc6d282b2010-10-14 21:42:15 -07002117 // Touch Size
2118 switch (mCalibration.touchSizeCalibration) {
2119 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2120 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002121 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002122 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2123 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002124 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002125 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2126 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002127 break;
2128 default:
2129 assert(false);
2130 }
2131
Jeff Brownc6d282b2010-10-14 21:42:15 -07002132 // Tool Size
2133 switch (mCalibration.toolSizeCalibration) {
2134 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2135 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002136 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002137 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2138 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002139 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002140 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2141 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2142 break;
2143 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2144 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002145 break;
2146 default:
2147 assert(false);
2148 }
2149
Jeff Brownc6d282b2010-10-14 21:42:15 -07002150 if (mCalibration.haveToolSizeLinearScale) {
2151 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2152 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002153 }
2154
Jeff Brownc6d282b2010-10-14 21:42:15 -07002155 if (mCalibration.haveToolSizeLinearBias) {
2156 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2157 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002158 }
2159
Jeff Brownc6d282b2010-10-14 21:42:15 -07002160 if (mCalibration.haveToolSizeAreaScale) {
2161 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2162 mCalibration.toolSizeAreaScale);
2163 }
2164
2165 if (mCalibration.haveToolSizeAreaBias) {
2166 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2167 mCalibration.toolSizeAreaBias);
2168 }
2169
2170 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002171 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002172 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002173 }
2174
2175 // Pressure
2176 switch (mCalibration.pressureCalibration) {
2177 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002178 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002179 break;
2180 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002181 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002182 break;
2183 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002184 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002185 break;
2186 default:
2187 assert(false);
2188 }
2189
2190 switch (mCalibration.pressureSource) {
2191 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002192 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002193 break;
2194 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002195 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002196 break;
2197 case Calibration::PRESSURE_SOURCE_DEFAULT:
2198 break;
2199 default:
2200 assert(false);
2201 }
2202
2203 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002204 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2205 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002206 }
2207
2208 // Size
2209 switch (mCalibration.sizeCalibration) {
2210 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002211 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002212 break;
2213 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002214 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002215 break;
2216 default:
2217 assert(false);
2218 }
2219
2220 // Orientation
2221 switch (mCalibration.orientationCalibration) {
2222 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002223 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002224 break;
2225 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002226 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002227 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002228 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2229 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2230 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002231 default:
2232 assert(false);
2233 }
2234}
2235
Jeff Brown6d0fec22010-07-23 21:28:06 -07002236void TouchInputMapper::reset() {
2237 // Synthesize touch up event if touch is currently down.
2238 // This will also take care of finishing virtual key processing if needed.
2239 if (mLastTouch.pointerCount != 0) {
2240 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2241 mCurrentTouch.clear();
2242 syncTouch(when, true);
2243 }
2244
Jeff Brown6328cdc2010-07-29 18:18:33 -07002245 { // acquire lock
2246 AutoMutex _l(mLock);
2247 initializeLocked();
2248 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002249
Jeff Brown6328cdc2010-07-29 18:18:33 -07002250 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002251}
2252
2253void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002254 uint32_t policyFlags = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002255
Jeff Brown6328cdc2010-07-29 18:18:33 -07002256 // Preprocess pointer data.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002257
Jeff Brown6d0fec22010-07-23 21:28:06 -07002258 if (mParameters.useBadTouchFilter) {
2259 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002260 havePointerIds = false;
2261 }
2262 }
2263
Jeff Brown6d0fec22010-07-23 21:28:06 -07002264 if (mParameters.useJumpyTouchFilter) {
2265 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002266 havePointerIds = false;
2267 }
2268 }
2269
2270 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002271 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002272 }
2273
Jeff Brown6d0fec22010-07-23 21:28:06 -07002274 TouchData temp;
2275 TouchData* savedTouch;
2276 if (mParameters.useAveragingTouchFilter) {
2277 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002278 savedTouch = & temp;
2279
Jeff Brown6d0fec22010-07-23 21:28:06 -07002280 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002281 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002282 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002283 }
2284
Jeff Brown6328cdc2010-07-29 18:18:33 -07002285 // Process touches and virtual keys.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002286
Jeff Brown6d0fec22010-07-23 21:28:06 -07002287 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2288 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002289 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002290 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002291 }
2292
Jeff Brown6328cdc2010-07-29 18:18:33 -07002293 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002294
Jeff Brown6d0fec22010-07-23 21:28:06 -07002295 if (touchResult == DROP_STROKE) {
2296 mLastTouch.clear();
2297 } else {
2298 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002299 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002300}
2301
Jeff Brown6d0fec22010-07-23 21:28:06 -07002302TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2303 nsecs_t when, uint32_t policyFlags) {
2304 int32_t keyEventAction, keyEventFlags;
2305 int32_t keyCode, scanCode, downTime;
2306 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002307
Jeff Brown6328cdc2010-07-29 18:18:33 -07002308 { // acquire lock
2309 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002310
Jeff Brown6328cdc2010-07-29 18:18:33 -07002311 // Update surface size and orientation, including virtual key positions.
2312 if (! configureSurfaceLocked()) {
2313 return DROP_STROKE;
2314 }
2315
2316 // Check for virtual key press.
2317 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002318 if (mCurrentTouch.pointerCount == 0) {
2319 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002320 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002321#if DEBUG_VIRTUAL_KEYS
2322 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002323 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002324#endif
2325 keyEventAction = AKEY_EVENT_ACTION_UP;
2326 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2327 touchResult = SKIP_TOUCH;
2328 goto DispatchVirtualKey;
2329 }
2330
2331 if (mCurrentTouch.pointerCount == 1) {
2332 int32_t x = mCurrentTouch.pointers[0].x;
2333 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002334 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2335 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002336 // Pointer is still within the space of the virtual key.
2337 return SKIP_TOUCH;
2338 }
2339 }
2340
2341 // Pointer left virtual key area or another pointer also went down.
2342 // Send key cancellation and drop the stroke so subsequent motions will be
2343 // considered fresh downs. This is useful when the user swipes away from the
2344 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002345 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002346#if DEBUG_VIRTUAL_KEYS
2347 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002348 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002349#endif
2350 keyEventAction = AKEY_EVENT_ACTION_UP;
2351 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2352 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002353
2354 // Check whether the pointer moved inside the display area where we should
2355 // start a new stroke.
2356 int32_t x = mCurrentTouch.pointers[0].x;
2357 int32_t y = mCurrentTouch.pointers[0].y;
2358 if (isPointInsideSurfaceLocked(x, y)) {
2359 mLastTouch.clear();
2360 touchResult = DISPATCH_TOUCH;
2361 } else {
2362 touchResult = DROP_STROKE;
2363 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002364 } else {
2365 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2366 // Pointer just went down. Handle off-screen touches, if needed.
2367 int32_t x = mCurrentTouch.pointers[0].x;
2368 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002369 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002370 // If exactly one pointer went down, check for virtual key hit.
2371 // Otherwise we will drop the entire stroke.
2372 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002373 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002374 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002375 if (mContext->shouldDropVirtualKey(when, getDevice(),
2376 virtualKey->keyCode, virtualKey->scanCode)) {
2377 return DROP_STROKE;
2378 }
2379
Jeff Brown6328cdc2010-07-29 18:18:33 -07002380 mLocked.currentVirtualKey.down = true;
2381 mLocked.currentVirtualKey.downTime = when;
2382 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2383 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002384#if DEBUG_VIRTUAL_KEYS
2385 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002386 mLocked.currentVirtualKey.keyCode,
2387 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002388#endif
2389 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2390 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2391 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2392 touchResult = SKIP_TOUCH;
2393 goto DispatchVirtualKey;
2394 }
2395 }
2396 return DROP_STROKE;
2397 }
2398 }
2399 return DISPATCH_TOUCH;
2400 }
2401
2402 DispatchVirtualKey:
2403 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002404 keyCode = mLocked.currentVirtualKey.keyCode;
2405 scanCode = mLocked.currentVirtualKey.scanCode;
2406 downTime = mLocked.currentVirtualKey.downTime;
2407 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002408
2409 // Dispatch virtual key.
2410 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002411 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002412 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2413 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2414 return touchResult;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002415}
2416
Jeff Brownfe508922011-01-18 15:10:10 -08002417void TouchInputMapper::detectGestures(nsecs_t when) {
2418 // Disable all virtual key touches that happen within a short time interval of the
2419 // most recent touch. The idea is to filter out stray virtual key presses when
2420 // interacting with the touch screen.
2421 //
2422 // Problems we're trying to solve:
2423 //
2424 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2425 // virtual key area that is implemented by a separate touch panel and accidentally
2426 // triggers a virtual key.
2427 //
2428 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2429 // area and accidentally triggers a virtual key. This often happens when virtual keys
2430 // are layed out below the screen near to where the on screen keyboard's space bar
2431 // is displayed.
2432 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2433 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2434 }
2435}
2436
Jeff Brown6d0fec22010-07-23 21:28:06 -07002437void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2438 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2439 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002440 if (currentPointerCount == 0 && lastPointerCount == 0) {
2441 return; // nothing to do!
2442 }
2443
Jeff Brown6d0fec22010-07-23 21:28:06 -07002444 BitSet32 currentIdBits = mCurrentTouch.idBits;
2445 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002446
2447 if (currentIdBits == lastIdBits) {
2448 // No pointer id changes so this is a move event.
2449 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002450 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002451 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002452 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002453 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002454 // There may be pointers going up and pointers going down and pointers moving
2455 // all at the same time.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002456 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2457 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2458 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002459 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002460
Jeff Brownc3db8582010-10-20 15:33:38 -07002461 // Produce an intermediate representation of the touch data that consists of the
2462 // old location of pointers that have just gone up and the new location of pointers that
2463 // have just moved but omits the location of pointers that have just gone down.
2464 TouchData interimTouch;
2465 interimTouch.copyFrom(mLastTouch);
2466
2467 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2468 bool moveNeeded = false;
2469 while (!moveIdBits.isEmpty()) {
2470 uint32_t moveId = moveIdBits.firstMarkedBit();
2471 moveIdBits.clearBit(moveId);
2472
2473 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2474 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2475 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2476 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2477 moveNeeded = true;
2478 }
2479 }
2480
2481 // Dispatch pointer up events using the interim pointer locations.
2482 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002483 uint32_t upId = upIdBits.firstMarkedBit();
2484 upIdBits.clearBit(upId);
2485 BitSet32 oldActiveIdBits = activeIdBits;
2486 activeIdBits.clearBit(upId);
2487
2488 int32_t motionEventAction;
2489 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002490 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002491 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002492 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002493 }
2494
Jeff Brownc3db8582010-10-20 15:33:38 -07002495 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002496 oldActiveIdBits, upId, pointerCount, motionEventAction);
2497 pointerCount -= 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002498 }
2499
Jeff Brownc3db8582010-10-20 15:33:38 -07002500 // Dispatch move events if any of the remaining pointers moved from their old locations.
2501 // Although applications receive new locations as part of individual pointer up
2502 // events, they do not generally handle them except when presented in a move event.
2503 if (moveNeeded) {
2504 dispatchTouch(when, policyFlags, &mCurrentTouch,
2505 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2506 }
2507
2508 // Dispatch pointer down events using the new pointer locations.
2509 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002510 uint32_t downId = downIdBits.firstMarkedBit();
2511 downIdBits.clearBit(downId);
2512 BitSet32 oldActiveIdBits = activeIdBits;
2513 activeIdBits.markBit(downId);
2514
2515 int32_t motionEventAction;
2516 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002517 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002518 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002519 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002520 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002521 }
2522
Jeff Brown8d608662010-08-30 03:02:23 -07002523 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002524 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002525 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002526 }
2527 }
2528}
2529
Jeff Brown6d0fec22010-07-23 21:28:06 -07002530void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002531 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002532 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002533 int32_t pointerIds[MAX_POINTERS];
2534 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac02010-04-22 18:58:52 -07002535 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002536 float xPrecision, yPrecision;
2537
2538 { // acquire lock
2539 AutoMutex _l(mLock);
2540
2541 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2542 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002543 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002544 uint32_t id = idBits.firstMarkedBit();
2545 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002546 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002547
Jeff Brown8d608662010-08-30 03:02:23 -07002548 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002549
Jeff Brown8d608662010-08-30 03:02:23 -07002550 // X and Y
2551 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2552 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002553
Jeff Brown8d608662010-08-30 03:02:23 -07002554 // ToolMajor and ToolMinor
2555 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002556 switch (mCalibration.toolSizeCalibration) {
2557 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002558 toolMajor = in.toolMajor * mLocked.geometricScale;
2559 if (mRawAxes.toolMinor.valid) {
2560 toolMinor = in.toolMinor * mLocked.geometricScale;
2561 } else {
2562 toolMinor = toolMajor;
2563 }
2564 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002565 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002566 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002567 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002568 : 0;
2569 if (mRawAxes.toolMinor.valid) {
2570 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002571 ? in.toolMinor * mLocked.toolSizeLinearScale
2572 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002573 : 0;
2574 } else {
2575 toolMinor = toolMajor;
2576 }
2577 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002578 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2579 if (in.toolMajor != 0) {
2580 float diameter = sqrtf(in.toolMajor
2581 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2582 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2583 } else {
2584 toolMajor = 0;
2585 }
2586 toolMinor = toolMajor;
2587 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002588 default:
2589 toolMajor = 0;
2590 toolMinor = 0;
2591 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002592 }
2593
Jeff Brownc6d282b2010-10-14 21:42:15 -07002594 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002595 toolMajor /= pointerCount;
2596 toolMinor /= pointerCount;
2597 }
2598
2599 // Pressure
2600 float rawPressure;
2601 switch (mCalibration.pressureSource) {
2602 case Calibration::PRESSURE_SOURCE_PRESSURE:
2603 rawPressure = in.pressure;
2604 break;
2605 case Calibration::PRESSURE_SOURCE_TOUCH:
2606 rawPressure = in.touchMajor;
2607 break;
2608 default:
2609 rawPressure = 0;
2610 }
2611
2612 float pressure;
2613 switch (mCalibration.pressureCalibration) {
2614 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2615 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2616 pressure = rawPressure * mLocked.pressureScale;
2617 break;
2618 default:
2619 pressure = 1;
2620 break;
2621 }
2622
2623 // TouchMajor and TouchMinor
2624 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002625 switch (mCalibration.touchSizeCalibration) {
2626 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002627 touchMajor = in.touchMajor * mLocked.geometricScale;
2628 if (mRawAxes.touchMinor.valid) {
2629 touchMinor = in.touchMinor * mLocked.geometricScale;
2630 } else {
2631 touchMinor = touchMajor;
2632 }
2633 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002634 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002635 touchMajor = toolMajor * pressure;
2636 touchMinor = toolMinor * pressure;
2637 break;
2638 default:
2639 touchMajor = 0;
2640 touchMinor = 0;
2641 break;
2642 }
2643
2644 if (touchMajor > toolMajor) {
2645 touchMajor = toolMajor;
2646 }
2647 if (touchMinor > toolMinor) {
2648 touchMinor = toolMinor;
2649 }
2650
2651 // Size
2652 float size;
2653 switch (mCalibration.sizeCalibration) {
2654 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2655 float rawSize = mRawAxes.toolMinor.valid
2656 ? avg(in.toolMajor, in.toolMinor)
2657 : in.toolMajor;
2658 size = rawSize * mLocked.sizeScale;
2659 break;
2660 }
2661 default:
2662 size = 0;
2663 break;
2664 }
2665
2666 // Orientation
2667 float orientation;
2668 switch (mCalibration.orientationCalibration) {
2669 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2670 orientation = in.orientation * mLocked.orientationScale;
2671 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002672 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2673 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2674 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2675 if (c1 != 0 || c2 != 0) {
2676 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002677 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2678 touchMajor *= scale;
2679 touchMinor /= scale;
2680 toolMajor *= scale;
2681 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002682 } else {
2683 orientation = 0;
2684 }
2685 break;
2686 }
Jeff Brown8d608662010-08-30 03:02:23 -07002687 default:
2688 orientation = 0;
2689 }
2690
2691 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002692 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002693 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002694 float xTemp = x;
2695 x = y;
2696 y = mLocked.surfaceWidth - xTemp;
2697 orientation -= M_PI_2;
2698 if (orientation < - M_PI_2) {
2699 orientation += M_PI;
2700 }
2701 break;
2702 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002703 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002704 x = mLocked.surfaceWidth - x;
2705 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002706 break;
2707 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002708 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002709 float xTemp = x;
2710 x = mLocked.surfaceHeight - y;
2711 y = xTemp;
2712 orientation += M_PI_2;
2713 if (orientation > M_PI_2) {
2714 orientation -= M_PI;
2715 }
2716 break;
2717 }
2718 }
2719
Jeff Brown8d608662010-08-30 03:02:23 -07002720 // Write output coords.
2721 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002722 out.clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -08002723 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2724 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2725 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2726 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2727 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2728 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2729 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2730 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2731 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002732
Jeff Brown8d608662010-08-30 03:02:23 -07002733 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002734
2735 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002736 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002737 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002738 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002739
2740 // Check edge flags by looking only at the first pointer since the flags are
2741 // global to the event.
2742 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownebbd5d12011-02-17 13:01:34 -08002743 float x = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
2744 float y = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08002745
2746 if (x <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002747 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002748 } else if (x >= mLocked.orientedSurfaceWidth) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002749 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2750 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08002751 if (y <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002752 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002753 } else if (y >= mLocked.orientedSurfaceHeight) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002754 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2755 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002756 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002757
2758 xPrecision = mLocked.orientedXPrecision;
2759 yPrecision = mLocked.orientedYPrecision;
2760 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07002761
Jeff Brown83c09682010-12-23 17:50:18 -08002762 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002763 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002764 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002765 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002766}
2767
Jeff Brown6328cdc2010-07-29 18:18:33 -07002768bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002769 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2770 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2771 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002772 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002773 return true;
2774}
2775
Jeff Brown6328cdc2010-07-29 18:18:33 -07002776const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2777 int32_t x, int32_t y) {
2778 size_t numVirtualKeys = mLocked.virtualKeys.size();
2779 for (size_t i = 0; i < numVirtualKeys; i++) {
2780 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002781
2782#if DEBUG_VIRTUAL_KEYS
2783 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2784 "left=%d, top=%d, right=%d, bottom=%d",
2785 x, y,
2786 virtualKey.keyCode, virtualKey.scanCode,
2787 virtualKey.hitLeft, virtualKey.hitTop,
2788 virtualKey.hitRight, virtualKey.hitBottom);
2789#endif
2790
2791 if (virtualKey.isHit(x, y)) {
2792 return & virtualKey;
2793 }
2794 }
2795
2796 return NULL;
2797}
2798
2799void TouchInputMapper::calculatePointerIds() {
2800 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2801 uint32_t lastPointerCount = mLastTouch.pointerCount;
2802
2803 if (currentPointerCount == 0) {
2804 // No pointers to assign.
2805 mCurrentTouch.idBits.clear();
2806 } else if (lastPointerCount == 0) {
2807 // All pointers are new.
2808 mCurrentTouch.idBits.clear();
2809 for (uint32_t i = 0; i < currentPointerCount; i++) {
2810 mCurrentTouch.pointers[i].id = i;
2811 mCurrentTouch.idToIndex[i] = i;
2812 mCurrentTouch.idBits.markBit(i);
2813 }
2814 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2815 // Only one pointer and no change in count so it must have the same id as before.
2816 uint32_t id = mLastTouch.pointers[0].id;
2817 mCurrentTouch.pointers[0].id = id;
2818 mCurrentTouch.idToIndex[id] = 0;
2819 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2820 } else {
2821 // General case.
2822 // We build a heap of squared euclidean distances between current and last pointers
2823 // associated with the current and last pointer indices. Then, we find the best
2824 // match (by distance) for each current pointer.
2825 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2826
2827 uint32_t heapSize = 0;
2828 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2829 currentPointerIndex++) {
2830 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2831 lastPointerIndex++) {
2832 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2833 - mLastTouch.pointers[lastPointerIndex].x;
2834 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2835 - mLastTouch.pointers[lastPointerIndex].y;
2836
2837 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2838
2839 // Insert new element into the heap (sift up).
2840 heap[heapSize].currentPointerIndex = currentPointerIndex;
2841 heap[heapSize].lastPointerIndex = lastPointerIndex;
2842 heap[heapSize].distance = distance;
2843 heapSize += 1;
2844 }
2845 }
2846
2847 // Heapify
2848 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2849 startIndex -= 1;
2850 for (uint32_t parentIndex = startIndex; ;) {
2851 uint32_t childIndex = parentIndex * 2 + 1;
2852 if (childIndex >= heapSize) {
2853 break;
2854 }
2855
2856 if (childIndex + 1 < heapSize
2857 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2858 childIndex += 1;
2859 }
2860
2861 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2862 break;
2863 }
2864
2865 swap(heap[parentIndex], heap[childIndex]);
2866 parentIndex = childIndex;
2867 }
2868 }
2869
2870#if DEBUG_POINTER_ASSIGNMENT
2871 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2872 for (size_t i = 0; i < heapSize; i++) {
2873 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2874 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2875 heap[i].distance);
2876 }
2877#endif
2878
2879 // Pull matches out by increasing order of distance.
2880 // To avoid reassigning pointers that have already been matched, the loop keeps track
2881 // of which last and current pointers have been matched using the matchedXXXBits variables.
2882 // It also tracks the used pointer id bits.
2883 BitSet32 matchedLastBits(0);
2884 BitSet32 matchedCurrentBits(0);
2885 BitSet32 usedIdBits(0);
2886 bool first = true;
2887 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2888 for (;;) {
2889 if (first) {
2890 // The first time through the loop, we just consume the root element of
2891 // the heap (the one with smallest distance).
2892 first = false;
2893 } else {
2894 // Previous iterations consumed the root element of the heap.
2895 // Pop root element off of the heap (sift down).
2896 heapSize -= 1;
2897 assert(heapSize > 0);
2898
2899 // Sift down.
2900 heap[0] = heap[heapSize];
2901 for (uint32_t parentIndex = 0; ;) {
2902 uint32_t childIndex = parentIndex * 2 + 1;
2903 if (childIndex >= heapSize) {
2904 break;
2905 }
2906
2907 if (childIndex + 1 < heapSize
2908 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2909 childIndex += 1;
2910 }
2911
2912 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2913 break;
2914 }
2915
2916 swap(heap[parentIndex], heap[childIndex]);
2917 parentIndex = childIndex;
2918 }
2919
2920#if DEBUG_POINTER_ASSIGNMENT
2921 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2922 for (size_t i = 0; i < heapSize; i++) {
2923 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2924 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2925 heap[i].distance);
2926 }
2927#endif
2928 }
2929
2930 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2931 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2932
2933 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2934 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2935
2936 matchedCurrentBits.markBit(currentPointerIndex);
2937 matchedLastBits.markBit(lastPointerIndex);
2938
2939 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2940 mCurrentTouch.pointers[currentPointerIndex].id = id;
2941 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2942 usedIdBits.markBit(id);
2943
2944#if DEBUG_POINTER_ASSIGNMENT
2945 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2946 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2947#endif
2948 break;
2949 }
2950 }
2951
2952 // Assign fresh ids to new pointers.
2953 if (currentPointerCount > lastPointerCount) {
2954 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2955 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2956 uint32_t id = usedIdBits.firstUnmarkedBit();
2957
2958 mCurrentTouch.pointers[currentPointerIndex].id = id;
2959 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2960 usedIdBits.markBit(id);
2961
2962#if DEBUG_POINTER_ASSIGNMENT
2963 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2964 currentPointerIndex, id);
2965#endif
2966
2967 if (--i == 0) break; // done
2968 matchedCurrentBits.markBit(currentPointerIndex);
2969 }
2970 }
2971
2972 // Fix id bits.
2973 mCurrentTouch.idBits = usedIdBits;
2974 }
2975}
2976
2977/* Special hack for devices that have bad screen data: if one of the
2978 * points has moved more than a screen height from the last position,
2979 * then drop it. */
2980bool TouchInputMapper::applyBadTouchFilter() {
2981 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002982 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002983 return false;
2984 }
2985
2986 uint32_t pointerCount = mCurrentTouch.pointerCount;
2987
2988 // Nothing to do if there are no points.
2989 if (pointerCount == 0) {
2990 return false;
2991 }
2992
2993 // Don't do anything if a finger is going down or up. We run
2994 // here before assigning pointer IDs, so there isn't a good
2995 // way to do per-finger matching.
2996 if (pointerCount != mLastTouch.pointerCount) {
2997 return false;
2998 }
2999
3000 // We consider a single movement across more than a 7/16 of
3001 // the long size of the screen to be bad. This was a magic value
3002 // determined by looking at the maximum distance it is feasible
3003 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07003004 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003005
3006 // XXX The original code in InputDevice.java included commented out
3007 // code for testing the X axis. Note that when we drop a point
3008 // we don't actually restore the old X either. Strange.
3009 // The old code also tries to track when bad points were previously
3010 // detected but it turns out that due to the placement of a "break"
3011 // at the end of the loop, we never set mDroppedBadPoint to true
3012 // so it is effectively dead code.
3013 // Need to figure out if the old code is busted or just overcomplicated
3014 // but working as intended.
3015
3016 // Look through all new points and see if any are farther than
3017 // acceptable from all previous points.
3018 for (uint32_t i = pointerCount; i-- > 0; ) {
3019 int32_t y = mCurrentTouch.pointers[i].y;
3020 int32_t closestY = INT_MAX;
3021 int32_t closestDeltaY = 0;
3022
3023#if DEBUG_HACKS
3024 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3025#endif
3026
3027 for (uint32_t j = pointerCount; j-- > 0; ) {
3028 int32_t lastY = mLastTouch.pointers[j].y;
3029 int32_t deltaY = abs(y - lastY);
3030
3031#if DEBUG_HACKS
3032 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3033 j, lastY, deltaY);
3034#endif
3035
3036 if (deltaY < maxDeltaY) {
3037 goto SkipSufficientlyClosePoint;
3038 }
3039 if (deltaY < closestDeltaY) {
3040 closestDeltaY = deltaY;
3041 closestY = lastY;
3042 }
3043 }
3044
3045 // Must not have found a close enough match.
3046#if DEBUG_HACKS
3047 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3048 i, y, closestY, closestDeltaY, maxDeltaY);
3049#endif
3050
3051 mCurrentTouch.pointers[i].y = closestY;
3052 return true; // XXX original code only corrects one point
3053
3054 SkipSufficientlyClosePoint: ;
3055 }
3056
3057 // No change.
3058 return false;
3059}
3060
3061/* Special hack for devices that have bad screen data: drop points where
3062 * the coordinate value for one axis has jumped to the other pointer's location.
3063 */
3064bool TouchInputMapper::applyJumpyTouchFilter() {
3065 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003066 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003067 return false;
3068 }
3069
3070 uint32_t pointerCount = mCurrentTouch.pointerCount;
3071 if (mLastTouch.pointerCount != pointerCount) {
3072#if DEBUG_HACKS
3073 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3074 mLastTouch.pointerCount, pointerCount);
3075 for (uint32_t i = 0; i < pointerCount; i++) {
3076 LOGD(" Pointer %d (%d, %d)", i,
3077 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3078 }
3079#endif
3080
3081 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3082 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3083 // Just drop the first few events going from 1 to 2 pointers.
3084 // They're bad often enough that they're not worth considering.
3085 mCurrentTouch.pointerCount = 1;
3086 mJumpyTouchFilter.jumpyPointsDropped += 1;
3087
3088#if DEBUG_HACKS
3089 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3090#endif
3091 return true;
3092 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3093 // The event when we go from 2 -> 1 tends to be messed up too
3094 mCurrentTouch.pointerCount = 2;
3095 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3096 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3097 mJumpyTouchFilter.jumpyPointsDropped += 1;
3098
3099#if DEBUG_HACKS
3100 for (int32_t i = 0; i < 2; i++) {
3101 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3102 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3103 }
3104#endif
3105 return true;
3106 }
3107 }
3108 // Reset jumpy points dropped on other transitions or if limit exceeded.
3109 mJumpyTouchFilter.jumpyPointsDropped = 0;
3110
3111#if DEBUG_HACKS
3112 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3113#endif
3114 return false;
3115 }
3116
3117 // We have the same number of pointers as last time.
3118 // A 'jumpy' point is one where the coordinate value for one axis
3119 // has jumped to the other pointer's location. No need to do anything
3120 // else if we only have one pointer.
3121 if (pointerCount < 2) {
3122 return false;
3123 }
3124
3125 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003126 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003127
3128 // We only replace the single worst jumpy point as characterized by pointer distance
3129 // in a single axis.
3130 int32_t badPointerIndex = -1;
3131 int32_t badPointerReplacementIndex = -1;
3132 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3133
3134 for (uint32_t i = pointerCount; i-- > 0; ) {
3135 int32_t x = mCurrentTouch.pointers[i].x;
3136 int32_t y = mCurrentTouch.pointers[i].y;
3137
3138#if DEBUG_HACKS
3139 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3140#endif
3141
3142 // Check if a touch point is too close to another's coordinates
3143 bool dropX = false, dropY = false;
3144 for (uint32_t j = 0; j < pointerCount; j++) {
3145 if (i == j) {
3146 continue;
3147 }
3148
3149 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3150 dropX = true;
3151 break;
3152 }
3153
3154 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3155 dropY = true;
3156 break;
3157 }
3158 }
3159 if (! dropX && ! dropY) {
3160 continue; // not jumpy
3161 }
3162
3163 // Find a replacement candidate by comparing with older points on the
3164 // complementary (non-jumpy) axis.
3165 int32_t distance = INT_MIN; // distance to be corrected
3166 int32_t replacementIndex = -1;
3167
3168 if (dropX) {
3169 // X looks too close. Find an older replacement point with a close Y.
3170 int32_t smallestDeltaY = INT_MAX;
3171 for (uint32_t j = 0; j < pointerCount; j++) {
3172 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3173 if (deltaY < smallestDeltaY) {
3174 smallestDeltaY = deltaY;
3175 replacementIndex = j;
3176 }
3177 }
3178 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3179 } else {
3180 // Y looks too close. Find an older replacement point with a close X.
3181 int32_t smallestDeltaX = INT_MAX;
3182 for (uint32_t j = 0; j < pointerCount; j++) {
3183 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3184 if (deltaX < smallestDeltaX) {
3185 smallestDeltaX = deltaX;
3186 replacementIndex = j;
3187 }
3188 }
3189 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3190 }
3191
3192 // If replacing this pointer would correct a worse error than the previous ones
3193 // considered, then use this replacement instead.
3194 if (distance > badPointerDistance) {
3195 badPointerIndex = i;
3196 badPointerReplacementIndex = replacementIndex;
3197 badPointerDistance = distance;
3198 }
3199 }
3200
3201 // Correct the jumpy pointer if one was found.
3202 if (badPointerIndex >= 0) {
3203#if DEBUG_HACKS
3204 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3205 badPointerIndex,
3206 mLastTouch.pointers[badPointerReplacementIndex].x,
3207 mLastTouch.pointers[badPointerReplacementIndex].y);
3208#endif
3209
3210 mCurrentTouch.pointers[badPointerIndex].x =
3211 mLastTouch.pointers[badPointerReplacementIndex].x;
3212 mCurrentTouch.pointers[badPointerIndex].y =
3213 mLastTouch.pointers[badPointerReplacementIndex].y;
3214 mJumpyTouchFilter.jumpyPointsDropped += 1;
3215 return true;
3216 }
3217 }
3218
3219 mJumpyTouchFilter.jumpyPointsDropped = 0;
3220 return false;
3221}
3222
3223/* Special hack for devices that have bad screen data: aggregate and
3224 * compute averages of the coordinate data, to reduce the amount of
3225 * jitter seen by applications. */
3226void TouchInputMapper::applyAveragingTouchFilter() {
3227 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3228 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3229 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3230 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003231 int32_t pressure;
3232 switch (mCalibration.pressureSource) {
3233 case Calibration::PRESSURE_SOURCE_PRESSURE:
3234 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3235 break;
3236 case Calibration::PRESSURE_SOURCE_TOUCH:
3237 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3238 break;
3239 default:
3240 pressure = 1;
3241 break;
3242 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003243
3244 if (mLastTouch.idBits.hasBit(id)) {
3245 // Pointer was down before and is still down now.
3246 // Compute average over history trace.
3247 uint32_t start = mAveragingTouchFilter.historyStart[id];
3248 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3249
3250 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3251 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3252 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3253
3254#if DEBUG_HACKS
3255 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3256 id, distance);
3257#endif
3258
3259 if (distance < AVERAGING_DISTANCE_LIMIT) {
3260 // Increment end index in preparation for recording new historical data.
3261 end += 1;
3262 if (end > AVERAGING_HISTORY_SIZE) {
3263 end = 0;
3264 }
3265
3266 // If the end index has looped back to the start index then we have filled
3267 // the historical trace up to the desired size so we drop the historical
3268 // data at the start of the trace.
3269 if (end == start) {
3270 start += 1;
3271 if (start > AVERAGING_HISTORY_SIZE) {
3272 start = 0;
3273 }
3274 }
3275
3276 // Add the raw data to the historical trace.
3277 mAveragingTouchFilter.historyStart[id] = start;
3278 mAveragingTouchFilter.historyEnd[id] = end;
3279 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3280 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3281 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3282
3283 // Average over all historical positions in the trace by total pressure.
3284 int32_t averagedX = 0;
3285 int32_t averagedY = 0;
3286 int32_t totalPressure = 0;
3287 for (;;) {
3288 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3289 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3290 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3291 .pointers[id].pressure;
3292
3293 averagedX += historicalX * historicalPressure;
3294 averagedY += historicalY * historicalPressure;
3295 totalPressure += historicalPressure;
3296
3297 if (start == end) {
3298 break;
3299 }
3300
3301 start += 1;
3302 if (start > AVERAGING_HISTORY_SIZE) {
3303 start = 0;
3304 }
3305 }
3306
Jeff Brown8d608662010-08-30 03:02:23 -07003307 if (totalPressure != 0) {
3308 averagedX /= totalPressure;
3309 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003310
3311#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003312 LOGD("AveragingTouchFilter: Pointer id %d - "
3313 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3314 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003315#endif
3316
Jeff Brown8d608662010-08-30 03:02:23 -07003317 mCurrentTouch.pointers[currentIndex].x = averagedX;
3318 mCurrentTouch.pointers[currentIndex].y = averagedY;
3319 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003320 } else {
3321#if DEBUG_HACKS
3322 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3323#endif
3324 }
3325 } else {
3326#if DEBUG_HACKS
3327 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3328#endif
3329 }
3330
3331 // Reset pointer history.
3332 mAveragingTouchFilter.historyStart[id] = 0;
3333 mAveragingTouchFilter.historyEnd[id] = 0;
3334 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3335 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3336 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3337 }
3338}
3339
3340int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003341 { // acquire lock
3342 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003343
Jeff Brown6328cdc2010-07-29 18:18:33 -07003344 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003345 return AKEY_STATE_VIRTUAL;
3346 }
3347
Jeff Brown6328cdc2010-07-29 18:18:33 -07003348 size_t numVirtualKeys = mLocked.virtualKeys.size();
3349 for (size_t i = 0; i < numVirtualKeys; i++) {
3350 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003351 if (virtualKey.keyCode == keyCode) {
3352 return AKEY_STATE_UP;
3353 }
3354 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003355 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003356
3357 return AKEY_STATE_UNKNOWN;
3358}
3359
3360int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003361 { // acquire lock
3362 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003363
Jeff Brown6328cdc2010-07-29 18:18:33 -07003364 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003365 return AKEY_STATE_VIRTUAL;
3366 }
3367
Jeff Brown6328cdc2010-07-29 18:18:33 -07003368 size_t numVirtualKeys = mLocked.virtualKeys.size();
3369 for (size_t i = 0; i < numVirtualKeys; i++) {
3370 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003371 if (virtualKey.scanCode == scanCode) {
3372 return AKEY_STATE_UP;
3373 }
3374 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003375 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003376
3377 return AKEY_STATE_UNKNOWN;
3378}
3379
3380bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3381 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003382 { // acquire lock
3383 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003384
Jeff Brown6328cdc2010-07-29 18:18:33 -07003385 size_t numVirtualKeys = mLocked.virtualKeys.size();
3386 for (size_t i = 0; i < numVirtualKeys; i++) {
3387 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003388
3389 for (size_t i = 0; i < numCodes; i++) {
3390 if (virtualKey.keyCode == keyCodes[i]) {
3391 outFlags[i] = 1;
3392 }
3393 }
3394 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003395 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003396
3397 return true;
3398}
3399
3400
3401// --- SingleTouchInputMapper ---
3402
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003403SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3404 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003405 initialize();
3406}
3407
3408SingleTouchInputMapper::~SingleTouchInputMapper() {
3409}
3410
3411void SingleTouchInputMapper::initialize() {
3412 mAccumulator.clear();
3413
3414 mDown = false;
3415 mX = 0;
3416 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003417 mPressure = 0; // default to 0 for devices that don't report pressure
3418 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003419}
3420
3421void SingleTouchInputMapper::reset() {
3422 TouchInputMapper::reset();
3423
Jeff Brown6d0fec22010-07-23 21:28:06 -07003424 initialize();
3425 }
3426
3427void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3428 switch (rawEvent->type) {
3429 case EV_KEY:
3430 switch (rawEvent->scanCode) {
3431 case BTN_TOUCH:
3432 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3433 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003434 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3435 // not have received valid position information yet. This logic assumes that
3436 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003437 break;
3438 }
3439 break;
3440
3441 case EV_ABS:
3442 switch (rawEvent->scanCode) {
3443 case ABS_X:
3444 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3445 mAccumulator.absX = rawEvent->value;
3446 break;
3447 case ABS_Y:
3448 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3449 mAccumulator.absY = rawEvent->value;
3450 break;
3451 case ABS_PRESSURE:
3452 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3453 mAccumulator.absPressure = rawEvent->value;
3454 break;
3455 case ABS_TOOL_WIDTH:
3456 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3457 mAccumulator.absToolWidth = rawEvent->value;
3458 break;
3459 }
3460 break;
3461
3462 case EV_SYN:
3463 switch (rawEvent->scanCode) {
3464 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003465 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003466 break;
3467 }
3468 break;
3469 }
3470}
3471
3472void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003473 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003474 if (fields == 0) {
3475 return; // no new state changes, so nothing to do
3476 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003477
3478 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3479 mDown = mAccumulator.btnTouch;
3480 }
3481
3482 if (fields & Accumulator::FIELD_ABS_X) {
3483 mX = mAccumulator.absX;
3484 }
3485
3486 if (fields & Accumulator::FIELD_ABS_Y) {
3487 mY = mAccumulator.absY;
3488 }
3489
3490 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3491 mPressure = mAccumulator.absPressure;
3492 }
3493
3494 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003495 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003496 }
3497
3498 mCurrentTouch.clear();
3499
3500 if (mDown) {
3501 mCurrentTouch.pointerCount = 1;
3502 mCurrentTouch.pointers[0].id = 0;
3503 mCurrentTouch.pointers[0].x = mX;
3504 mCurrentTouch.pointers[0].y = mY;
3505 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003506 mCurrentTouch.pointers[0].touchMajor = 0;
3507 mCurrentTouch.pointers[0].touchMinor = 0;
3508 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3509 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003510 mCurrentTouch.pointers[0].orientation = 0;
3511 mCurrentTouch.idToIndex[0] = 0;
3512 mCurrentTouch.idBits.markBit(0);
3513 }
3514
3515 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003516
3517 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003518}
3519
Jeff Brown8d608662010-08-30 03:02:23 -07003520void SingleTouchInputMapper::configureRawAxes() {
3521 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003522
Jeff Brown8d608662010-08-30 03:02:23 -07003523 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3524 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3525 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3526 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003527}
3528
3529
3530// --- MultiTouchInputMapper ---
3531
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003532MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3533 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003534 initialize();
3535}
3536
3537MultiTouchInputMapper::~MultiTouchInputMapper() {
3538}
3539
3540void MultiTouchInputMapper::initialize() {
3541 mAccumulator.clear();
3542}
3543
3544void MultiTouchInputMapper::reset() {
3545 TouchInputMapper::reset();
3546
Jeff Brown6d0fec22010-07-23 21:28:06 -07003547 initialize();
3548}
3549
3550void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3551 switch (rawEvent->type) {
3552 case EV_ABS: {
3553 uint32_t pointerIndex = mAccumulator.pointerCount;
3554 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3555
3556 switch (rawEvent->scanCode) {
3557 case ABS_MT_POSITION_X:
3558 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3559 pointer->absMTPositionX = rawEvent->value;
3560 break;
3561 case ABS_MT_POSITION_Y:
3562 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3563 pointer->absMTPositionY = rawEvent->value;
3564 break;
3565 case ABS_MT_TOUCH_MAJOR:
3566 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3567 pointer->absMTTouchMajor = rawEvent->value;
3568 break;
3569 case ABS_MT_TOUCH_MINOR:
3570 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3571 pointer->absMTTouchMinor = rawEvent->value;
3572 break;
3573 case ABS_MT_WIDTH_MAJOR:
3574 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3575 pointer->absMTWidthMajor = rawEvent->value;
3576 break;
3577 case ABS_MT_WIDTH_MINOR:
3578 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3579 pointer->absMTWidthMinor = rawEvent->value;
3580 break;
3581 case ABS_MT_ORIENTATION:
3582 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3583 pointer->absMTOrientation = rawEvent->value;
3584 break;
3585 case ABS_MT_TRACKING_ID:
3586 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3587 pointer->absMTTrackingId = rawEvent->value;
3588 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003589 case ABS_MT_PRESSURE:
3590 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3591 pointer->absMTPressure = rawEvent->value;
3592 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003593 }
3594 break;
3595 }
3596
3597 case EV_SYN:
3598 switch (rawEvent->scanCode) {
3599 case SYN_MT_REPORT: {
3600 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3601 uint32_t pointerIndex = mAccumulator.pointerCount;
3602
3603 if (mAccumulator.pointers[pointerIndex].fields) {
3604 if (pointerIndex == MAX_POINTERS) {
3605 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3606 MAX_POINTERS);
3607 } else {
3608 pointerIndex += 1;
3609 mAccumulator.pointerCount = pointerIndex;
3610 }
3611 }
3612
3613 mAccumulator.pointers[pointerIndex].clear();
3614 break;
3615 }
3616
3617 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003618 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003619 break;
3620 }
3621 break;
3622 }
3623}
3624
3625void MultiTouchInputMapper::sync(nsecs_t when) {
3626 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003627 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003628
Jeff Brown6d0fec22010-07-23 21:28:06 -07003629 uint32_t inCount = mAccumulator.pointerCount;
3630 uint32_t outCount = 0;
3631 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003632
Jeff Brown6d0fec22010-07-23 21:28:06 -07003633 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003634
Jeff Brown6d0fec22010-07-23 21:28:06 -07003635 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003636 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3637 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003638
Jeff Brown6d0fec22010-07-23 21:28:06 -07003639 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003640 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3641 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07003642 continue;
3643 }
3644
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003645 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3646 outPointer.x = inPointer.absMTPositionX;
3647 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003648
Jeff Brown8d608662010-08-30 03:02:23 -07003649 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3650 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003651 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3652 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003653 continue;
3654 }
Jeff Brown8d608662010-08-30 03:02:23 -07003655 outPointer.pressure = inPointer.absMTPressure;
3656 } else {
3657 // Default pressure to 0 if absent.
3658 outPointer.pressure = 0;
3659 }
3660
3661 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3662 if (inPointer.absMTTouchMajor <= 0) {
3663 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3664 // a pointer going up. Drop this finger.
3665 continue;
3666 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003667 outPointer.touchMajor = inPointer.absMTTouchMajor;
3668 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003669 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003670 outPointer.touchMajor = 0;
3671 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003672
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003673 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3674 outPointer.touchMinor = inPointer.absMTTouchMinor;
3675 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003676 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003677 outPointer.touchMinor = outPointer.touchMajor;
3678 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003679
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003680 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3681 outPointer.toolMajor = inPointer.absMTWidthMajor;
3682 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003683 // Default tool area to 0 if absent.
3684 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003685 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003686
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003687 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3688 outPointer.toolMinor = inPointer.absMTWidthMinor;
3689 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003690 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003691 outPointer.toolMinor = outPointer.toolMajor;
3692 }
3693
3694 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3695 outPointer.orientation = inPointer.absMTOrientation;
3696 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003697 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003698 outPointer.orientation = 0;
3699 }
3700
Jeff Brown8d608662010-08-30 03:02:23 -07003701 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003702 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003703 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3704 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003705
Jeff Brown6d0fec22010-07-23 21:28:06 -07003706 if (id > MAX_POINTER_ID) {
3707#if DEBUG_POINTERS
3708 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003709 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003710 id, MAX_POINTER_ID);
3711#endif
3712 havePointerIds = false;
3713 }
3714 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003715 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003716 mCurrentTouch.idToIndex[id] = outCount;
3717 mCurrentTouch.idBits.markBit(id);
3718 }
3719 } else {
3720 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003721 }
3722 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003723
Jeff Brown6d0fec22010-07-23 21:28:06 -07003724 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003725 }
3726
Jeff Brown6d0fec22010-07-23 21:28:06 -07003727 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003728
Jeff Brown6d0fec22010-07-23 21:28:06 -07003729 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003730
3731 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003732}
3733
Jeff Brown8d608662010-08-30 03:02:23 -07003734void MultiTouchInputMapper::configureRawAxes() {
3735 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003736
Jeff Brown8d608662010-08-30 03:02:23 -07003737 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3738 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3739 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3740 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3741 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3742 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3743 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3744 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003745}
3746
Jeff Brown46b9ac02010-04-22 18:58:52 -07003747
Jeff Browncb1404e2011-01-15 18:14:15 -08003748// --- JoystickInputMapper ---
3749
3750JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3751 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08003752}
3753
3754JoystickInputMapper::~JoystickInputMapper() {
3755}
3756
3757uint32_t JoystickInputMapper::getSources() {
3758 return AINPUT_SOURCE_JOYSTICK;
3759}
3760
3761void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3762 InputMapper::populateDeviceInfo(info);
3763
Jeff Brown6f2fba42011-02-19 01:08:02 -08003764 for (size_t i = 0; i < mAxes.size(); i++) {
3765 const Axis& axis = mAxes.valueAt(i);
3766 info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003767 }
3768}
3769
3770void JoystickInputMapper::dump(String8& dump) {
3771 dump.append(INDENT2 "Joystick Input Mapper:\n");
3772
Jeff Brown6f2fba42011-02-19 01:08:02 -08003773 dump.append(INDENT3 "Axes:\n");
3774 size_t numAxes = mAxes.size();
3775 for (size_t i = 0; i < numAxes; i++) {
3776 const Axis& axis = mAxes.valueAt(i);
3777 const char* label = getAxisLabel(axis.axis);
3778 char name[32];
3779 if (label) {
3780 strncpy(name, label, sizeof(name));
3781 name[sizeof(name) - 1] = '\0';
3782 } else {
3783 snprintf(name, sizeof(name), "%d", axis.axis);
3784 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003785 dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
Jeff Brown6f2fba42011-02-19 01:08:02 -08003786 "scale=%0.3f, offset=%0.3f\n",
Jeff Browncb1404e2011-01-15 18:14:15 -08003787 name, axis.min, axis.max, axis.flat, axis.fuzz,
Jeff Brown6f2fba42011-02-19 01:08:02 -08003788 axis.scale, axis.offset);
3789 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3790 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3791 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003792 }
3793}
3794
3795void JoystickInputMapper::configure() {
3796 InputMapper::configure();
3797
Jeff Brown6f2fba42011-02-19 01:08:02 -08003798 // Collect all axes.
3799 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3800 RawAbsoluteAxisInfo rawAxisInfo;
3801 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3802 if (rawAxisInfo.valid) {
3803 int32_t axisId;
3804 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
3805 if (!explicitlyMapped) {
3806 // Axis is not explicitly mapped, will choose a generic axis later.
3807 axisId = -1;
3808 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003809
Jeff Brown6f2fba42011-02-19 01:08:02 -08003810 Axis axis;
3811 if (isCenteredAxis(axisId)) {
3812 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3813 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
3814 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3815 scale, offset, -1.0f, 1.0f,
3816 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3817 } else {
3818 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3819 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3820 scale, 0.0f, 0.0f, 1.0f,
3821 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3822 }
3823
3824 // To eliminate noise while the joystick is at rest, filter out small variations
3825 // in axis values up front.
3826 axis.filter = axis.flat * 0.25f;
3827
3828 mAxes.add(abs, axis);
3829 }
3830 }
3831
3832 // If there are too many axes, start dropping them.
3833 // Prefer to keep explicitly mapped axes.
3834 if (mAxes.size() > PointerCoords::MAX_AXES) {
3835 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3836 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3837 pruneAxes(true);
3838 pruneAxes(false);
3839 }
3840
3841 // Assign generic axis ids to remaining axes.
3842 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3843 size_t numAxes = mAxes.size();
3844 for (size_t i = 0; i < numAxes; i++) {
3845 Axis& axis = mAxes.editValueAt(i);
3846 if (axis.axis < 0) {
3847 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3848 && haveAxis(nextGenericAxisId)) {
3849 nextGenericAxisId += 1;
3850 }
3851
3852 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
3853 axis.axis = nextGenericAxisId;
3854 nextGenericAxisId += 1;
3855 } else {
3856 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3857 "have already been assigned to other axes.",
3858 getDeviceName().string(), mAxes.keyAt(i));
3859 mAxes.removeItemsAt(i--);
3860 numAxes -= 1;
3861 }
3862 }
3863 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003864}
3865
Jeff Brown6f2fba42011-02-19 01:08:02 -08003866bool JoystickInputMapper::haveAxis(int32_t axis) {
3867 size_t numAxes = mAxes.size();
3868 for (size_t i = 0; i < numAxes; i++) {
3869 if (mAxes.valueAt(i).axis == axis) {
3870 return true;
3871 }
3872 }
3873 return false;
3874}
Jeff Browncb1404e2011-01-15 18:14:15 -08003875
Jeff Brown6f2fba42011-02-19 01:08:02 -08003876void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
3877 size_t i = mAxes.size();
3878 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
3879 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
3880 continue;
3881 }
3882 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
3883 getDeviceName().string(), mAxes.keyAt(i));
3884 mAxes.removeItemsAt(i);
3885 }
3886}
3887
3888bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
3889 switch (axis) {
3890 case AMOTION_EVENT_AXIS_X:
3891 case AMOTION_EVENT_AXIS_Y:
3892 case AMOTION_EVENT_AXIS_Z:
3893 case AMOTION_EVENT_AXIS_RX:
3894 case AMOTION_EVENT_AXIS_RY:
3895 case AMOTION_EVENT_AXIS_RZ:
3896 case AMOTION_EVENT_AXIS_HAT_X:
3897 case AMOTION_EVENT_AXIS_HAT_Y:
3898 case AMOTION_EVENT_AXIS_ORIENTATION:
3899 return true;
3900 default:
3901 return false;
3902 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003903}
3904
3905void JoystickInputMapper::reset() {
3906 // Recenter all axes.
3907 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08003908
Jeff Brown6f2fba42011-02-19 01:08:02 -08003909 size_t numAxes = mAxes.size();
3910 for (size_t i = 0; i < numAxes; i++) {
3911 Axis& axis = mAxes.editValueAt(i);
3912 axis.newValue = 0;
3913 }
3914
3915 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08003916
3917 InputMapper::reset();
3918}
3919
3920void JoystickInputMapper::process(const RawEvent* rawEvent) {
3921 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003922 case EV_ABS: {
3923 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
3924 if (index >= 0) {
3925 Axis& axis = mAxes.editValueAt(index);
3926 float newValue = rawEvent->value * axis.scale + axis.offset;
3927 if (newValue != axis.newValue) {
3928 axis.newValue = newValue;
3929 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003930 }
3931 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08003932 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003933
3934 case EV_SYN:
3935 switch (rawEvent->scanCode) {
3936 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08003937 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08003938 break;
3939 }
3940 break;
3941 }
3942}
3943
Jeff Brown6f2fba42011-02-19 01:08:02 -08003944void JoystickInputMapper::sync(nsecs_t when, bool force) {
3945 if (!force && !haveAxesChangedSignificantly()) {
3946 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08003947 }
3948
3949 int32_t metaState = mContext->getGlobalMetaState();
3950
Jeff Brown6f2fba42011-02-19 01:08:02 -08003951 PointerCoords pointerCoords;
3952 pointerCoords.clear();
3953
3954 size_t numAxes = mAxes.size();
3955 for (size_t i = 0; i < numAxes; i++) {
3956 Axis& axis = mAxes.editValueAt(i);
3957 pointerCoords.setAxisValue(axis.axis, axis.newValue);
3958 axis.oldValue = axis.newValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08003959 }
3960
Jeff Brown6f2fba42011-02-19 01:08:02 -08003961 int32_t pointerId = 0;
3962 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3963 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3964 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08003965}
3966
Jeff Brown6f2fba42011-02-19 01:08:02 -08003967bool JoystickInputMapper::haveAxesChangedSignificantly() {
3968 size_t numAxes = mAxes.size();
3969 for (size_t i = 0; i < numAxes; i++) {
3970 const Axis& axis = mAxes.valueAt(i);
3971 if (axis.newValue != axis.oldValue
3972 && fabs(axis.newValue - axis.oldValue) > axis.filter) {
3973 return true;
3974 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003975 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08003976 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08003977}
3978
Jeff Brown46b9ac02010-04-22 18:58:52 -07003979} // namespace android