blob: 88084c019c28853964801eabe7504f423d67ef6d [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brownf4a4ec22010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Browne839a582010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
Jeff Brown38a7fab2010-08-30 03:02:23 -070029#include <stdlib.h>
Jeff Browne839a582010-04-22 18:58:52 -070030#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070031#include <errno.h>
32#include <limits.h>
Jeff Brown5c1ed842010-07-14 18:48:53 -070033#include <math.h>
Jeff Browne839a582010-04-22 18:58:52 -070034
Jeff Brown38a7fab2010-08-30 03:02:23 -070035#define INDENT " "
36
Jeff Browne839a582010-04-22 18:58:52 -070037namespace android {
38
39// --- Static Functions ---
40
41template<typename T>
42inline static T abs(const T& value) {
43 return value < 0 ? - value : value;
44}
45
46template<typename T>
47inline static T min(const T& a, const T& b) {
48 return a < b ? a : b;
49}
50
Jeff Brownf4a4ec22010-06-16 01:53:36 -070051template<typename T>
52inline static void swap(T& a, T& b) {
53 T temp = a;
54 a = b;
55 b = temp;
56}
57
Jeff Brown38a7fab2010-08-30 03:02:23 -070058inline static float avg(float x, float y) {
59 return (x + y) / 2;
60}
61
62inline static float pythag(float x, float y) {
63 return sqrtf(x * x + y * y);
64}
65
Jeff Brownf4a4ec22010-06-16 01:53:36 -070066
Jeff Browne839a582010-04-22 18:58:52 -070067int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
68 int32_t mask;
69 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070070 case AKEYCODE_ALT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070071 mask = AMETA_ALT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070072 break;
Jeff Brown8575a872010-06-30 16:10:35 -070073 case AKEYCODE_ALT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070074 mask = AMETA_ALT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070075 break;
Jeff Brown8575a872010-06-30 16:10:35 -070076 case AKEYCODE_SHIFT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070077 mask = AMETA_SHIFT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070078 break;
Jeff Brown8575a872010-06-30 16:10:35 -070079 case AKEYCODE_SHIFT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070080 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070081 break;
Jeff Brown8575a872010-06-30 16:10:35 -070082 case AKEYCODE_SYM:
Jeff Brown5c1ed842010-07-14 18:48:53 -070083 mask = AMETA_SYM_ON;
Jeff Browne839a582010-04-22 18:58:52 -070084 break;
85 default:
86 return oldMetaState;
87 }
88
89 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brown5c1ed842010-07-14 18:48:53 -070090 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Browne839a582010-04-22 18:58:52 -070091
Jeff Brown5c1ed842010-07-14 18:48:53 -070092 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
93 newMetaState |= AMETA_ALT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070094 }
95
Jeff Brown5c1ed842010-07-14 18:48:53 -070096 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
97 newMetaState |= AMETA_SHIFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070098 }
99
100 return newMetaState;
101}
102
103static const int32_t keyCodeRotationMap[][4] = {
104 // key codes enumerated counter-clockwise with the original (unrotated) key first
105 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brown8575a872010-06-30 16:10:35 -0700106 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
107 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
108 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
109 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Browne839a582010-04-22 18:58:52 -0700110};
111static const int keyCodeRotationMapSize =
112 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
113
114int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700115 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-04-22 18:58:52 -0700116 for (int i = 0; i < keyCodeRotationMapSize; i++) {
117 if (keyCode == keyCodeRotationMap[i][0]) {
118 return keyCodeRotationMap[i][orientation];
119 }
120 }
121 }
122 return keyCode;
123}
124
Jeff Browne57e8952010-07-23 21:28:06 -0700125static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
126 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
127}
128
Jeff Browne839a582010-04-22 18:58:52 -0700129
Jeff Brown38a7fab2010-08-30 03:02:23 -0700130// --- InputDeviceCalibration ---
131
132InputDeviceCalibration::InputDeviceCalibration() {
133}
134
135void InputDeviceCalibration::clear() {
136 mProperties.clear();
137}
138
139void InputDeviceCalibration::addProperty(const String8& key, const String8& value) {
140 mProperties.add(key, value);
141}
142
143bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const {
144 ssize_t index = mProperties.indexOfKey(key);
145 if (index < 0) {
146 return false;
147 }
148
149 outValue = mProperties.valueAt(index);
150 return true;
151}
152
153bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const {
154 String8 stringValue;
155 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
156 return false;
157 }
158
159 char* end;
160 int value = strtol(stringValue.string(), & end, 10);
161 if (*end != '\0') {
162 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.",
163 key.string(), stringValue.string());
164 return false;
165 }
166 outValue = value;
167 return true;
168}
169
170bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const {
171 String8 stringValue;
172 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
173 return false;
174 }
175
176 char* end;
177 float value = strtof(stringValue.string(), & end);
178 if (*end != '\0') {
179 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.",
180 key.string(), stringValue.string());
181 return false;
182 }
183 outValue = value;
184 return true;
185}
186
187
Jeff Browne839a582010-04-22 18:58:52 -0700188// --- InputReader ---
189
190InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700191 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700192 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Browne57e8952010-07-23 21:28:06 -0700193 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
194 mGlobalMetaState(0) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700195 configureExcludedDevices();
Jeff Browne57e8952010-07-23 21:28:06 -0700196 updateGlobalMetaState();
197 updateInputConfiguration();
Jeff Browne839a582010-04-22 18:58:52 -0700198}
199
200InputReader::~InputReader() {
201 for (size_t i = 0; i < mDevices.size(); i++) {
202 delete mDevices.valueAt(i);
203 }
204}
205
206void InputReader::loopOnce() {
207 RawEvent rawEvent;
Jeff Browne57e8952010-07-23 21:28:06 -0700208 mEventHub->getEvent(& rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700209
210#if DEBUG_RAW_EVENTS
211 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
212 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
213 rawEvent.value);
214#endif
215
216 process(& rawEvent);
217}
218
219void InputReader::process(const RawEvent* rawEvent) {
220 switch (rawEvent->type) {
221 case EventHubInterface::DEVICE_ADDED:
Jeff Browne57e8952010-07-23 21:28:06 -0700222 addDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700223 break;
224
225 case EventHubInterface::DEVICE_REMOVED:
Jeff Browne57e8952010-07-23 21:28:06 -0700226 removeDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700227 break;
228
Jeff Browne57e8952010-07-23 21:28:06 -0700229 default:
230 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700231 break;
232 }
233}
234
Jeff Browne57e8952010-07-23 21:28:06 -0700235void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
236 String8 name = mEventHub->getDeviceName(deviceId);
237 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
238
Jeff Brown38a7fab2010-08-30 03:02:23 -0700239 // Write a log message about the added device as a heading for subsequent log messages.
240 LOGI("Device added: id=0x%x, name=%s", deviceId, name.string());
241
Jeff Browne57e8952010-07-23 21:28:06 -0700242 InputDevice* device = createDevice(deviceId, name, classes);
243 device->configure();
244
Jeff Brown38a7fab2010-08-30 03:02:23 -0700245 if (device->isIgnored()) {
246 LOGI(INDENT "Sources: none (device is ignored)");
247 } else {
248 LOGI(INDENT "Sources: 0x%08x", device->getSources());
249 }
250
Jeff Browne57e8952010-07-23 21:28:06 -0700251 bool added = false;
252 { // acquire device registry writer lock
253 RWLock::AutoWLock _wl(mDeviceRegistryLock);
254
255 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
256 if (deviceIndex < 0) {
257 mDevices.add(deviceId, device);
258 added = true;
259 }
260 } // release device registry writer lock
261
262 if (! added) {
263 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
264 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700265 return;
266 }
267
Jeff Browne57e8952010-07-23 21:28:06 -0700268 handleConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700269}
270
Jeff Browne57e8952010-07-23 21:28:06 -0700271void InputReader::removeDevice(nsecs_t when, int32_t deviceId) {
272 bool removed = false;
273 InputDevice* device = NULL;
274 { // acquire device registry writer lock
275 RWLock::AutoWLock _wl(mDeviceRegistryLock);
276
277 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
278 if (deviceIndex >= 0) {
279 device = mDevices.valueAt(deviceIndex);
280 mDevices.removeItemsAt(deviceIndex, 1);
281 removed = true;
282 }
283 } // release device registry writer lock
284
285 if (! removed) {
286 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700287 return;
288 }
289
Jeff Brown38a7fab2010-08-30 03:02:23 -0700290 // Write a log message about the removed device as a heading for subsequent log messages.
Jeff Browne57e8952010-07-23 21:28:06 -0700291 if (device->isIgnored()) {
292 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
293 device->getId(), device->getName().string());
294 } else {
295 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
296 device->getId(), device->getName().string(), device->getSources());
297 }
298
Jeff Brown38a7fab2010-08-30 03:02:23 -0700299 device->reset();
300
Jeff Browne57e8952010-07-23 21:28:06 -0700301 delete device;
302
303 handleConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700304}
305
Jeff Browne57e8952010-07-23 21:28:06 -0700306InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
307 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Browne839a582010-04-22 18:58:52 -0700308
Jeff Browne57e8952010-07-23 21:28:06 -0700309 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Browne839a582010-04-22 18:58:52 -0700310
Jeff Browne57e8952010-07-23 21:28:06 -0700311 // Switch-like devices.
312 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
313 device->addMapper(new SwitchInputMapper(device));
314 }
315
316 // Keyboard-like devices.
317 uint32_t keyboardSources = 0;
318 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
319 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
320 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
321 }
322 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
323 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
324 }
325 if (classes & INPUT_DEVICE_CLASS_DPAD) {
326 keyboardSources |= AINPUT_SOURCE_DPAD;
327 }
328 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
329 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
330 }
331
332 if (keyboardSources != 0) {
333 device->addMapper(new KeyboardInputMapper(device,
334 associatedDisplayId, keyboardSources, keyboardType));
335 }
336
337 // Trackball-like devices.
338 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
339 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
340 }
341
342 // Touchscreen-like devices.
343 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
344 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
345 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
346 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
347 }
348
349 return device;
350}
351
352void InputReader::consumeEvent(const RawEvent* rawEvent) {
353 int32_t deviceId = rawEvent->deviceId;
354
355 { // acquire device registry reader lock
356 RWLock::AutoRLock _rl(mDeviceRegistryLock);
357
358 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
359 if (deviceIndex < 0) {
360 LOGW("Discarding event for unknown deviceId %d.", deviceId);
361 return;
362 }
363
364 InputDevice* device = mDevices.valueAt(deviceIndex);
365 if (device->isIgnored()) {
366 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
367 return;
368 }
369
370 device->process(rawEvent);
371 } // release device registry reader lock
372}
373
374void InputReader::handleConfigurationChanged(nsecs_t when) {
375 // Reset global meta state because it depends on the list of all configured devices.
376 updateGlobalMetaState();
377
378 // Update input configuration.
379 updateInputConfiguration();
380
381 // Enqueue configuration changed.
382 mDispatcher->notifyConfigurationChanged(when);
383}
384
385void InputReader::configureExcludedDevices() {
386 Vector<String8> excludedDeviceNames;
387 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
388
389 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
390 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
391 }
392}
393
394void InputReader::updateGlobalMetaState() {
395 { // acquire state lock
396 AutoMutex _l(mStateLock);
397
398 mGlobalMetaState = 0;
399
400 { // acquire device registry reader lock
401 RWLock::AutoRLock _rl(mDeviceRegistryLock);
402
403 for (size_t i = 0; i < mDevices.size(); i++) {
404 InputDevice* device = mDevices.valueAt(i);
405 mGlobalMetaState |= device->getMetaState();
406 }
407 } // release device registry reader lock
408 } // release state lock
409}
410
411int32_t InputReader::getGlobalMetaState() {
412 { // acquire state lock
413 AutoMutex _l(mStateLock);
414
415 return mGlobalMetaState;
416 } // release state lock
417}
418
419void InputReader::updateInputConfiguration() {
420 { // acquire state lock
421 AutoMutex _l(mStateLock);
422
423 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
424 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
425 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
426 { // acquire device registry reader lock
427 RWLock::AutoRLock _rl(mDeviceRegistryLock);
428
429 InputDeviceInfo deviceInfo;
430 for (size_t i = 0; i < mDevices.size(); i++) {
431 InputDevice* device = mDevices.valueAt(i);
432 device->getDeviceInfo(& deviceInfo);
433 uint32_t sources = deviceInfo.getSources();
434
435 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
436 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
437 }
438 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
439 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
440 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
441 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
442 }
443 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
444 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Browne839a582010-04-22 18:58:52 -0700445 }
446 }
Jeff Browne57e8952010-07-23 21:28:06 -0700447 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700448
Jeff Browne57e8952010-07-23 21:28:06 -0700449 mInputConfiguration.touchScreen = touchScreenConfig;
450 mInputConfiguration.keyboard = keyboardConfig;
451 mInputConfiguration.navigation = navigationConfig;
452 } // release state lock
453}
454
455void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
456 { // acquire state lock
457 AutoMutex _l(mStateLock);
458
459 *outConfiguration = mInputConfiguration;
460 } // release state lock
461}
462
463status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
464 { // acquire device registry reader lock
465 RWLock::AutoRLock _rl(mDeviceRegistryLock);
466
467 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
468 if (deviceIndex < 0) {
469 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700470 }
471
Jeff Browne57e8952010-07-23 21:28:06 -0700472 InputDevice* device = mDevices.valueAt(deviceIndex);
473 if (device->isIgnored()) {
474 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700475 }
Jeff Browne57e8952010-07-23 21:28:06 -0700476
477 device->getDeviceInfo(outDeviceInfo);
478 return OK;
479 } // release device registy reader lock
480}
481
482void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
483 outDeviceIds.clear();
484
485 { // acquire device registry reader lock
486 RWLock::AutoRLock _rl(mDeviceRegistryLock);
487
488 size_t numDevices = mDevices.size();
489 for (size_t i = 0; i < numDevices; i++) {
490 InputDevice* device = mDevices.valueAt(i);
491 if (! device->isIgnored()) {
492 outDeviceIds.add(device->getId());
493 }
494 }
495 } // release device registy reader lock
496}
497
498int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
499 int32_t keyCode) {
500 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
501}
502
503int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
504 int32_t scanCode) {
505 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
506}
507
508int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
509 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
510}
511
512int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
513 GetStateFunc getStateFunc) {
514 { // acquire device registry reader lock
515 RWLock::AutoRLock _rl(mDeviceRegistryLock);
516
517 int32_t result = AKEY_STATE_UNKNOWN;
518 if (deviceId >= 0) {
519 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
520 if (deviceIndex >= 0) {
521 InputDevice* device = mDevices.valueAt(deviceIndex);
522 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
523 result = (device->*getStateFunc)(sourceMask, code);
524 }
525 }
526 } else {
527 size_t numDevices = mDevices.size();
528 for (size_t i = 0; i < numDevices; i++) {
529 InputDevice* device = mDevices.valueAt(i);
530 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
531 result = (device->*getStateFunc)(sourceMask, code);
532 if (result >= AKEY_STATE_DOWN) {
533 return result;
534 }
535 }
536 }
537 }
538 return result;
539 } // release device registy reader lock
540}
541
542bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
543 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
544 memset(outFlags, 0, numCodes);
545 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
546}
547
548bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
549 const int32_t* keyCodes, uint8_t* outFlags) {
550 { // acquire device registry reader lock
551 RWLock::AutoRLock _rl(mDeviceRegistryLock);
552 bool result = false;
553 if (deviceId >= 0) {
554 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
555 if (deviceIndex >= 0) {
556 InputDevice* device = mDevices.valueAt(deviceIndex);
557 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
558 result = device->markSupportedKeyCodes(sourceMask,
559 numCodes, keyCodes, outFlags);
560 }
561 }
562 } else {
563 size_t numDevices = mDevices.size();
564 for (size_t i = 0; i < numDevices; i++) {
565 InputDevice* device = mDevices.valueAt(i);
566 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
567 result |= device->markSupportedKeyCodes(sourceMask,
568 numCodes, keyCodes, outFlags);
569 }
570 }
571 }
572 return result;
573 } // release device registy reader lock
574}
575
Jeff Browna665ca82010-09-08 11:49:43 -0700576void InputReader::dump(String8& dump) {
577 dumpDeviceInfo(dump);
578}
579
580static void dumpMotionRange(String8& dump,
581 const char* name, const InputDeviceInfo::MotionRange* range) {
582 if (range) {
583 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
584 name, range->min, range->max, range->flat, range->fuzz);
585 }
586}
587
588#define DUMP_MOTION_RANGE(range) \
589 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
590
591void InputReader::dumpDeviceInfo(String8& dump) {
592 Vector<int32_t> deviceIds;
593 getInputDeviceIds(deviceIds);
594
595 InputDeviceInfo deviceInfo;
596 for (size_t i = 0; i < deviceIds.size(); i++) {
597 int32_t deviceId = deviceIds[i];
598
599 status_t result = getInputDeviceInfo(deviceId, & deviceInfo);
600 if (result == NAME_NOT_FOUND) {
601 continue;
602 } else if (result != OK) {
603 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
604 result);
605 continue;
606 }
607
608 dump.appendFormat(" Device %d: '%s'\n",
609 deviceInfo.getId(), deviceInfo.getName().string());
610 dump.appendFormat(" sources = 0x%08x\n",
611 deviceInfo.getSources());
612 dump.appendFormat(" keyboardType = %d\n",
613 deviceInfo.getKeyboardType());
614
615 dump.append(" motion ranges:\n");
616 DUMP_MOTION_RANGE(X);
617 DUMP_MOTION_RANGE(Y);
618 DUMP_MOTION_RANGE(PRESSURE);
619 DUMP_MOTION_RANGE(SIZE);
620 DUMP_MOTION_RANGE(TOUCH_MAJOR);
621 DUMP_MOTION_RANGE(TOUCH_MINOR);
622 DUMP_MOTION_RANGE(TOOL_MAJOR);
623 DUMP_MOTION_RANGE(TOOL_MINOR);
624 DUMP_MOTION_RANGE(ORIENTATION);
625 }
626}
627
628#undef DUMP_MOTION_RANGE
629
Jeff Browne57e8952010-07-23 21:28:06 -0700630
631// --- InputReaderThread ---
632
633InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
634 Thread(/*canCallJava*/ true), mReader(reader) {
635}
636
637InputReaderThread::~InputReaderThread() {
638}
639
640bool InputReaderThread::threadLoop() {
641 mReader->loopOnce();
642 return true;
643}
644
645
646// --- InputDevice ---
647
648InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
649 mContext(context), mId(id), mName(name), mSources(0) {
650}
651
652InputDevice::~InputDevice() {
653 size_t numMappers = mMappers.size();
654 for (size_t i = 0; i < numMappers; i++) {
655 delete mMappers[i];
656 }
657 mMappers.clear();
658}
659
660void InputDevice::addMapper(InputMapper* mapper) {
661 mMappers.add(mapper);
662}
663
664void InputDevice::configure() {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700665 if (! isIgnored()) {
666 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
667 }
668
Jeff Browne57e8952010-07-23 21:28:06 -0700669 mSources = 0;
670
671 size_t numMappers = mMappers.size();
672 for (size_t i = 0; i < numMappers; i++) {
673 InputMapper* mapper = mMappers[i];
674 mapper->configure();
675 mSources |= mapper->getSources();
Jeff Browne839a582010-04-22 18:58:52 -0700676 }
677}
678
Jeff Browne57e8952010-07-23 21:28:06 -0700679void InputDevice::reset() {
680 size_t numMappers = mMappers.size();
681 for (size_t i = 0; i < numMappers; i++) {
682 InputMapper* mapper = mMappers[i];
683 mapper->reset();
684 }
685}
Jeff Browne839a582010-04-22 18:58:52 -0700686
Jeff Browne57e8952010-07-23 21:28:06 -0700687void InputDevice::process(const RawEvent* rawEvent) {
688 size_t numMappers = mMappers.size();
689 for (size_t i = 0; i < numMappers; i++) {
690 InputMapper* mapper = mMappers[i];
691 mapper->process(rawEvent);
692 }
693}
Jeff Browne839a582010-04-22 18:58:52 -0700694
Jeff Browne57e8952010-07-23 21:28:06 -0700695void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
696 outDeviceInfo->initialize(mId, mName);
697
698 size_t numMappers = mMappers.size();
699 for (size_t i = 0; i < numMappers; i++) {
700 InputMapper* mapper = mMappers[i];
701 mapper->populateDeviceInfo(outDeviceInfo);
702 }
703}
704
705int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
706 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
707}
708
709int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
710 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
711}
712
713int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
714 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
715}
716
717int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
718 int32_t result = AKEY_STATE_UNKNOWN;
719 size_t numMappers = mMappers.size();
720 for (size_t i = 0; i < numMappers; i++) {
721 InputMapper* mapper = mMappers[i];
722 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
723 result = (mapper->*getStateFunc)(sourceMask, code);
724 if (result >= AKEY_STATE_DOWN) {
725 return result;
726 }
727 }
728 }
729 return result;
730}
731
732bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
733 const int32_t* keyCodes, uint8_t* outFlags) {
734 bool result = false;
735 size_t numMappers = mMappers.size();
736 for (size_t i = 0; i < numMappers; i++) {
737 InputMapper* mapper = mMappers[i];
738 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
739 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
740 }
741 }
742 return result;
743}
744
745int32_t InputDevice::getMetaState() {
746 int32_t result = 0;
747 size_t numMappers = mMappers.size();
748 for (size_t i = 0; i < numMappers; i++) {
749 InputMapper* mapper = mMappers[i];
750 result |= mapper->getMetaState();
751 }
752 return result;
753}
754
755
756// --- InputMapper ---
757
758InputMapper::InputMapper(InputDevice* device) :
759 mDevice(device), mContext(device->getContext()) {
760}
761
762InputMapper::~InputMapper() {
763}
764
765void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
766 info->addSource(getSources());
767}
768
769void InputMapper::configure() {
770}
771
772void InputMapper::reset() {
773}
774
775int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
776 return AKEY_STATE_UNKNOWN;
777}
778
779int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
780 return AKEY_STATE_UNKNOWN;
781}
782
783int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
784 return AKEY_STATE_UNKNOWN;
785}
786
787bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
788 const int32_t* keyCodes, uint8_t* outFlags) {
789 return false;
790}
791
792int32_t InputMapper::getMetaState() {
793 return 0;
794}
795
796bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
Jeff Browne57e8952010-07-23 21:28:06 -0700797 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
798}
799
800
801// --- SwitchInputMapper ---
802
803SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
804 InputMapper(device) {
805}
806
807SwitchInputMapper::~SwitchInputMapper() {
808}
809
810uint32_t SwitchInputMapper::getSources() {
811 return 0;
812}
813
814void SwitchInputMapper::process(const RawEvent* rawEvent) {
815 switch (rawEvent->type) {
816 case EV_SW:
817 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
818 break;
819 }
820}
821
822void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
823 uint32_t policyFlags = 0;
824 int32_t policyActions = getPolicy()->interceptSwitch(
825 when, switchCode, switchValue, policyFlags);
826
827 applyStandardPolicyActions(when, policyActions);
828}
829
830int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
831 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
832}
833
834
835// --- KeyboardInputMapper ---
836
837KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
838 uint32_t sources, int32_t keyboardType) :
839 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
840 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700841 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700842}
843
844KeyboardInputMapper::~KeyboardInputMapper() {
845}
846
Jeff Brownb51719b2010-07-29 18:18:33 -0700847void KeyboardInputMapper::initializeLocked() {
848 mLocked.metaState = AMETA_NONE;
849 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700850}
851
852uint32_t KeyboardInputMapper::getSources() {
853 return mSources;
854}
855
856void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
857 InputMapper::populateDeviceInfo(info);
858
859 info->setKeyboardType(mKeyboardType);
860}
861
862void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700863 for (;;) {
864 int32_t keyCode, scanCode;
865 { // acquire lock
866 AutoMutex _l(mLock);
867
868 // Synthesize key up event on reset if keys are currently down.
869 if (mLocked.keyDowns.isEmpty()) {
870 initializeLocked();
871 break; // done
872 }
873
874 const KeyDown& keyDown = mLocked.keyDowns.top();
875 keyCode = keyDown.keyCode;
876 scanCode = keyDown.scanCode;
877 } // release lock
878
Jeff Browne57e8952010-07-23 21:28:06 -0700879 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700880 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700881 }
882
883 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700884 getContext()->updateGlobalMetaState();
885}
886
887void KeyboardInputMapper::process(const RawEvent* rawEvent) {
888 switch (rawEvent->type) {
889 case EV_KEY: {
890 int32_t scanCode = rawEvent->scanCode;
891 if (isKeyboardOrGamepadKey(scanCode)) {
892 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
893 rawEvent->flags);
894 }
895 break;
896 }
897 }
898}
899
900bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
901 return scanCode < BTN_MOUSE
902 || scanCode >= KEY_OK
903 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
904}
905
Jeff Brownb51719b2010-07-29 18:18:33 -0700906void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
907 int32_t scanCode, uint32_t policyFlags) {
908 int32_t newMetaState;
909 nsecs_t downTime;
910 bool metaStateChanged = false;
911
912 { // acquire lock
913 AutoMutex _l(mLock);
914
915 if (down) {
916 // Rotate key codes according to orientation if needed.
917 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
918 if (mAssociatedDisplayId >= 0) {
919 int32_t orientation;
920 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
921 return;
922 }
923
924 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700925 }
926
Jeff Brownb51719b2010-07-29 18:18:33 -0700927 // Add key down.
928 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
929 if (keyDownIndex >= 0) {
930 // key repeat, be sure to use same keycode as before in case of rotation
931 keyCode = mLocked.keyDowns.top().keyCode;
932 } else {
933 // key down
934 mLocked.keyDowns.push();
935 KeyDown& keyDown = mLocked.keyDowns.editTop();
936 keyDown.keyCode = keyCode;
937 keyDown.scanCode = scanCode;
938 }
939
940 mLocked.downTime = when;
941 } else {
942 // Remove key down.
943 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
944 if (keyDownIndex >= 0) {
945 // key up, be sure to use same keycode as before in case of rotation
946 keyCode = mLocked.keyDowns.top().keyCode;
947 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
948 } else {
949 // key was not actually down
950 LOGI("Dropping key up from device %s because the key was not down. "
951 "keyCode=%d, scanCode=%d",
952 getDeviceName().string(), keyCode, scanCode);
953 return;
954 }
Jeff Browne57e8952010-07-23 21:28:06 -0700955 }
956
Jeff Brownb51719b2010-07-29 18:18:33 -0700957 int32_t oldMetaState = mLocked.metaState;
958 newMetaState = updateMetaState(keyCode, down, oldMetaState);
959 if (oldMetaState != newMetaState) {
960 mLocked.metaState = newMetaState;
961 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700962 }
Jeff Brown8575a872010-06-30 16:10:35 -0700963
Jeff Brownb51719b2010-07-29 18:18:33 -0700964 downTime = mLocked.downTime;
965 } // release lock
966
967 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700968 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700969 }
970
Jeff Brownb51719b2010-07-29 18:18:33 -0700971 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
972}
Jeff Browne839a582010-04-22 18:58:52 -0700973
Jeff Brownb51719b2010-07-29 18:18:33 -0700974void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
975 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -0700976 int32_t policyActions = getPolicy()->interceptKey(when,
977 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700978
Jeff Browne57e8952010-07-23 21:28:06 -0700979 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Browne839a582010-04-22 18:58:52 -0700980 return; // event dropped
981 }
982
Jeff Brownb51719b2010-07-29 18:18:33 -0700983 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700984 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Browne57e8952010-07-23 21:28:06 -0700985 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700986 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Browne839a582010-04-22 18:58:52 -0700987 }
988
Jeff Browne57e8952010-07-23 21:28:06 -0700989 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brownb51719b2010-07-29 18:18:33 -0700990 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700991}
992
Jeff Brownb51719b2010-07-29 18:18:33 -0700993ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
994 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -0700995 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700996 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -0700997 return i;
998 }
999 }
1000 return -1;
Jeff Browne839a582010-04-22 18:58:52 -07001001}
1002
Jeff Browne57e8952010-07-23 21:28:06 -07001003int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1004 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1005}
Jeff Browne839a582010-04-22 18:58:52 -07001006
Jeff Browne57e8952010-07-23 21:28:06 -07001007int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1008 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1009}
Jeff Browne839a582010-04-22 18:58:52 -07001010
Jeff Browne57e8952010-07-23 21:28:06 -07001011bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1012 const int32_t* keyCodes, uint8_t* outFlags) {
1013 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1014}
1015
1016int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001017 { // acquire lock
1018 AutoMutex _l(mLock);
1019 return mLocked.metaState;
1020 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001021}
1022
1023
1024// --- TrackballInputMapper ---
1025
1026TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1027 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1028 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1029 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1030 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1031 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1032
Jeff Brownb51719b2010-07-29 18:18:33 -07001033 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001034}
1035
1036TrackballInputMapper::~TrackballInputMapper() {
1037}
1038
1039uint32_t TrackballInputMapper::getSources() {
1040 return AINPUT_SOURCE_TRACKBALL;
1041}
1042
1043void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1044 InputMapper::populateDeviceInfo(info);
1045
1046 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1047 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1048}
1049
Jeff Brownb51719b2010-07-29 18:18:33 -07001050void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001051 mAccumulator.clear();
1052
Jeff Brownb51719b2010-07-29 18:18:33 -07001053 mLocked.down = false;
1054 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001055}
1056
1057void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001058 for (;;) {
1059 { // acquire lock
1060 AutoMutex _l(mLock);
1061
1062 if (! mLocked.down) {
1063 initializeLocked();
1064 break; // done
1065 }
1066 } // release lock
1067
1068 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001069 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001070 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001071 mAccumulator.btnMouse = false;
1072 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001073 }
1074
Jeff Browne57e8952010-07-23 21:28:06 -07001075 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001076}
Jeff Browne839a582010-04-22 18:58:52 -07001077
Jeff Browne57e8952010-07-23 21:28:06 -07001078void TrackballInputMapper::process(const RawEvent* rawEvent) {
1079 switch (rawEvent->type) {
1080 case EV_KEY:
1081 switch (rawEvent->scanCode) {
1082 case BTN_MOUSE:
1083 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1084 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001085 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1086 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001087 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001088 break;
Jeff Browne839a582010-04-22 18:58:52 -07001089 }
Jeff Browne57e8952010-07-23 21:28:06 -07001090 break;
Jeff Browne839a582010-04-22 18:58:52 -07001091
Jeff Browne57e8952010-07-23 21:28:06 -07001092 case EV_REL:
1093 switch (rawEvent->scanCode) {
1094 case REL_X:
1095 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1096 mAccumulator.relX = rawEvent->value;
1097 break;
1098 case REL_Y:
1099 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1100 mAccumulator.relY = rawEvent->value;
1101 break;
Jeff Browne839a582010-04-22 18:58:52 -07001102 }
Jeff Browne57e8952010-07-23 21:28:06 -07001103 break;
Jeff Browne839a582010-04-22 18:58:52 -07001104
Jeff Browne57e8952010-07-23 21:28:06 -07001105 case EV_SYN:
1106 switch (rawEvent->scanCode) {
1107 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001108 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001109 break;
Jeff Browne839a582010-04-22 18:58:52 -07001110 }
Jeff Browne57e8952010-07-23 21:28:06 -07001111 break;
Jeff Browne839a582010-04-22 18:58:52 -07001112 }
Jeff Browne839a582010-04-22 18:58:52 -07001113}
1114
Jeff Browne57e8952010-07-23 21:28:06 -07001115void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001116 uint32_t fields = mAccumulator.fields;
1117 if (fields == 0) {
1118 return; // no new state changes, so nothing to do
1119 }
1120
Jeff Brownb51719b2010-07-29 18:18:33 -07001121 int motionEventAction;
1122 PointerCoords pointerCoords;
1123 nsecs_t downTime;
1124 { // acquire lock
1125 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001126
Jeff Brownb51719b2010-07-29 18:18:33 -07001127 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1128
1129 if (downChanged) {
1130 if (mAccumulator.btnMouse) {
1131 mLocked.down = true;
1132 mLocked.downTime = when;
1133 } else {
1134 mLocked.down = false;
1135 }
Jeff Browne57e8952010-07-23 21:28:06 -07001136 }
Jeff Browne839a582010-04-22 18:58:52 -07001137
Jeff Brownb51719b2010-07-29 18:18:33 -07001138 downTime = mLocked.downTime;
1139 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1140 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001141
Jeff Brownb51719b2010-07-29 18:18:33 -07001142 if (downChanged) {
1143 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001144 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001145 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001146 }
Jeff Browne839a582010-04-22 18:58:52 -07001147
Jeff Brownb51719b2010-07-29 18:18:33 -07001148 pointerCoords.x = x;
1149 pointerCoords.y = y;
1150 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1151 pointerCoords.size = 0;
1152 pointerCoords.touchMajor = 0;
1153 pointerCoords.touchMinor = 0;
1154 pointerCoords.toolMajor = 0;
1155 pointerCoords.toolMinor = 0;
1156 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001157
Jeff Brownb51719b2010-07-29 18:18:33 -07001158 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1159 // Rotate motion based on display orientation if needed.
1160 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1161 int32_t orientation;
1162 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1163 return;
1164 }
1165
1166 float temp;
1167 switch (orientation) {
1168 case InputReaderPolicyInterface::ROTATION_90:
1169 temp = pointerCoords.x;
1170 pointerCoords.x = pointerCoords.y;
1171 pointerCoords.y = - temp;
1172 break;
1173
1174 case InputReaderPolicyInterface::ROTATION_180:
1175 pointerCoords.x = - pointerCoords.x;
1176 pointerCoords.y = - pointerCoords.y;
1177 break;
1178
1179 case InputReaderPolicyInterface::ROTATION_270:
1180 temp = pointerCoords.x;
1181 pointerCoords.x = - pointerCoords.y;
1182 pointerCoords.y = temp;
1183 break;
1184 }
1185 }
1186 } // release lock
1187
1188 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
Jeff Brownd64c8552010-08-17 20:38:35 -07001189
1190 mAccumulator.clear();
Jeff Brownb51719b2010-07-29 18:18:33 -07001191}
1192
1193void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1194 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001195 uint32_t policyFlags = 0;
1196 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1197
1198 if (! applyStandardPolicyActions(when, policyActions)) {
1199 return; // event dropped
1200 }
1201
Jeff Browne57e8952010-07-23 21:28:06 -07001202 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001203 int32_t pointerId = 0;
1204
Jeff Browne57e8952010-07-23 21:28:06 -07001205 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001206 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001207 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001208}
1209
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001210int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1211 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1212 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1213 } else {
1214 return AKEY_STATE_UNKNOWN;
1215 }
1216}
1217
Jeff Browne57e8952010-07-23 21:28:06 -07001218
1219// --- TouchInputMapper ---
1220
1221TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001222 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1223 mLocked.surfaceOrientation = -1;
1224 mLocked.surfaceWidth = -1;
1225 mLocked.surfaceHeight = -1;
1226
1227 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001228}
1229
1230TouchInputMapper::~TouchInputMapper() {
1231}
1232
1233uint32_t TouchInputMapper::getSources() {
1234 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1235}
1236
1237void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1238 InputMapper::populateDeviceInfo(info);
1239
Jeff Brownb51719b2010-07-29 18:18:33 -07001240 { // acquire lock
1241 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001242
Jeff Brownb51719b2010-07-29 18:18:33 -07001243 // Ensure surface information is up to date so that orientation changes are
1244 // noticed immediately.
1245 configureSurfaceLocked();
1246
1247 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1248 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001249
1250 if (mLocked.orientedRanges.havePressure) {
1251 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1252 mLocked.orientedRanges.pressure);
1253 }
1254
1255 if (mLocked.orientedRanges.haveSize) {
1256 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1257 mLocked.orientedRanges.size);
1258 }
1259
1260 if (mLocked.orientedRanges.haveTouchArea) {
1261 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1262 mLocked.orientedRanges.touchMajor);
1263 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1264 mLocked.orientedRanges.touchMinor);
1265 }
1266
1267 if (mLocked.orientedRanges.haveToolArea) {
1268 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1269 mLocked.orientedRanges.toolMajor);
1270 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1271 mLocked.orientedRanges.toolMinor);
1272 }
1273
1274 if (mLocked.orientedRanges.haveOrientation) {
1275 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1276 mLocked.orientedRanges.orientation);
1277 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001278 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001279}
1280
Jeff Brownb51719b2010-07-29 18:18:33 -07001281void TouchInputMapper::initializeLocked() {
1282 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001283 mLastTouch.clear();
1284 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001285
1286 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1287 mAveragingTouchFilter.historyStart[i] = 0;
1288 mAveragingTouchFilter.historyEnd[i] = 0;
1289 }
1290
1291 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001292
1293 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001294
1295 mLocked.orientedRanges.havePressure = false;
1296 mLocked.orientedRanges.haveSize = false;
1297 mLocked.orientedRanges.haveTouchArea = false;
1298 mLocked.orientedRanges.haveToolArea = false;
1299 mLocked.orientedRanges.haveOrientation = false;
1300}
1301
Jeff Browne57e8952010-07-23 21:28:06 -07001302void TouchInputMapper::configure() {
1303 InputMapper::configure();
1304
1305 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001306 configureParameters();
Jeff Browna665ca82010-09-08 11:49:43 -07001307 logParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001308
1309 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001310 configureRawAxes();
1311 logRawAxes();
1312
1313 // Prepare input device calibration.
1314 parseCalibration();
1315 resolveCalibration();
1316 logCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001317
Jeff Brownb51719b2010-07-29 18:18:33 -07001318 { // acquire lock
1319 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001320
Jeff Brown38a7fab2010-08-30 03:02:23 -07001321 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001322 configureSurfaceLocked();
1323 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001324}
1325
Jeff Brown38a7fab2010-08-30 03:02:23 -07001326void TouchInputMapper::configureParameters() {
1327 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1328 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1329 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1330}
1331
Jeff Browna665ca82010-09-08 11:49:43 -07001332void TouchInputMapper::logParameters() {
1333 if (mParameters.useBadTouchFilter) {
1334 LOGI(INDENT "Bad touch filter enabled.");
1335 }
1336 if (mParameters.useAveragingTouchFilter) {
1337 LOGI(INDENT "Averaging touch filter enabled.");
1338 }
1339 if (mParameters.useJumpyTouchFilter) {
1340 LOGI(INDENT "Jumpy touch filter enabled.");
1341 }
1342}
1343
Jeff Brown38a7fab2010-08-30 03:02:23 -07001344void TouchInputMapper::configureRawAxes() {
1345 mRawAxes.x.clear();
1346 mRawAxes.y.clear();
1347 mRawAxes.pressure.clear();
1348 mRawAxes.touchMajor.clear();
1349 mRawAxes.touchMinor.clear();
1350 mRawAxes.toolMajor.clear();
1351 mRawAxes.toolMinor.clear();
1352 mRawAxes.orientation.clear();
1353}
1354
Jeff Browna665ca82010-09-08 11:49:43 -07001355static void logAxisInfo(RawAbsoluteAxisInfo axis, const char* name) {
1356 if (axis.valid) {
1357 LOGI(INDENT "Raw %s axis: min=%d, max=%d, flat=%d, fuzz=%d",
1358 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1359 } else {
1360 LOGI(INDENT "Raw %s axis: unknown range", name);
1361 }
1362}
1363
Jeff Brown38a7fab2010-08-30 03:02:23 -07001364void TouchInputMapper::logRawAxes() {
1365 logAxisInfo(mRawAxes.x, "x");
1366 logAxisInfo(mRawAxes.y, "y");
1367 logAxisInfo(mRawAxes.pressure, "pressure");
1368 logAxisInfo(mRawAxes.touchMajor, "touchMajor");
1369 logAxisInfo(mRawAxes.touchMinor, "touchMinor");
1370 logAxisInfo(mRawAxes.toolMajor, "toolMajor");
1371 logAxisInfo(mRawAxes.toolMinor, "toolMinor");
1372 logAxisInfo(mRawAxes.orientation, "orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001373}
1374
Jeff Brownb51719b2010-07-29 18:18:33 -07001375bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001376 // Update orientation and dimensions if needed.
1377 int32_t orientation;
1378 int32_t width, height;
1379 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001380 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001381 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1382 return false;
1383 }
1384 } else {
1385 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001386 width = mRawAxes.x.getRange();
1387 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001388 }
1389
Jeff Brownb51719b2010-07-29 18:18:33 -07001390 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001391 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001392 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001393 }
1394
Jeff Brownb51719b2010-07-29 18:18:33 -07001395 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001396 if (sizeChanged) {
Jeff Browna665ca82010-09-08 11:49:43 -07001397 LOGI("Device reconfigured (display size changed): id=0x%x, name=%s",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001398 getDeviceId(), getDeviceName().string());
Jeff Browna665ca82010-09-08 11:49:43 -07001399 LOGI(INDENT "Width: %dpx", width);
1400 LOGI(INDENT "Height: %dpx", height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001401
Jeff Brownb51719b2010-07-29 18:18:33 -07001402 mLocked.surfaceWidth = width;
1403 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001404
Jeff Brown38a7fab2010-08-30 03:02:23 -07001405 // Configure X and Y factors.
1406 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1407 mLocked.xOrigin = mRawAxes.x.minValue;
1408 mLocked.yOrigin = mRawAxes.y.minValue;
1409 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1410 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001411 mLocked.xPrecision = 1.0f / mLocked.xScale;
1412 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001413
Jeff Brownb51719b2010-07-29 18:18:33 -07001414 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001415 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001416 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001417 mLocked.xOrigin = 0;
1418 mLocked.yOrigin = 0;
1419 mLocked.xScale = 1.0f;
1420 mLocked.yScale = 1.0f;
1421 mLocked.xPrecision = 1.0f;
1422 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001423 }
1424
Jeff Brown38a7fab2010-08-30 03:02:23 -07001425 // Scale factor for terms that are not oriented in a particular axis.
1426 // If the pixels are square then xScale == yScale otherwise we fake it
1427 // by choosing an average.
1428 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001429
Jeff Brown38a7fab2010-08-30 03:02:23 -07001430 // Size of diagonal axis.
1431 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001432
Jeff Brown38a7fab2010-08-30 03:02:23 -07001433 // TouchMajor and TouchMinor factors.
1434 if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) {
1435 mLocked.orientedRanges.haveTouchArea = true;
1436 mLocked.orientedRanges.touchMajor.min = 0;
1437 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1438 mLocked.orientedRanges.touchMajor.flat = 0;
1439 mLocked.orientedRanges.touchMajor.fuzz = 0;
1440 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1441 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001442
Jeff Brown38a7fab2010-08-30 03:02:23 -07001443 // ToolMajor and ToolMinor factors.
1444 if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1445 mLocked.toolAreaLinearScale = 0;
1446 mLocked.toolAreaLinearBias = 0;
1447 if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) {
1448 if (mCalibration.haveToolAreaLinearScale) {
1449 mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale;
1450 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1451 mLocked.toolAreaLinearScale = float(min(width, height))
1452 / mRawAxes.toolMajor.maxValue;
1453 }
1454
1455 if (mCalibration.haveToolAreaLinearBias) {
1456 mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias;
1457 }
1458 }
1459
1460 mLocked.orientedRanges.haveToolArea = true;
1461 mLocked.orientedRanges.toolMajor.min = 0;
1462 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1463 mLocked.orientedRanges.toolMajor.flat = 0;
1464 mLocked.orientedRanges.toolMajor.fuzz = 0;
1465 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1466 }
1467
1468 // Pressure factors.
1469 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1470 RawAbsoluteAxisInfo rawPressureAxis;
1471 switch (mCalibration.pressureSource) {
1472 case Calibration::PRESSURE_SOURCE_PRESSURE:
1473 rawPressureAxis = mRawAxes.pressure;
1474 break;
1475 case Calibration::PRESSURE_SOURCE_TOUCH:
1476 rawPressureAxis = mRawAxes.touchMajor;
1477 break;
1478 default:
1479 rawPressureAxis.clear();
1480 }
1481
1482 mLocked.pressureScale = 0;
1483 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1484 || mCalibration.pressureCalibration
1485 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1486 if (mCalibration.havePressureScale) {
1487 mLocked.pressureScale = mCalibration.pressureScale;
1488 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1489 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1490 }
1491 }
1492
1493 mLocked.orientedRanges.havePressure = true;
1494 mLocked.orientedRanges.pressure.min = 0;
1495 mLocked.orientedRanges.pressure.max = 1.0;
1496 mLocked.orientedRanges.pressure.flat = 0;
1497 mLocked.orientedRanges.pressure.fuzz = 0;
1498 }
1499
1500 // Size factors.
1501 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1502 mLocked.sizeScale = 0;
1503 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1504 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1505 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1506 }
1507 }
1508
1509 mLocked.orientedRanges.haveSize = true;
1510 mLocked.orientedRanges.size.min = 0;
1511 mLocked.orientedRanges.size.max = 1.0;
1512 mLocked.orientedRanges.size.flat = 0;
1513 mLocked.orientedRanges.size.fuzz = 0;
1514 }
1515
1516 // Orientation
1517 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1518 mLocked.orientationScale = 0;
1519 if (mCalibration.orientationCalibration
1520 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1521 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1522 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1523 }
1524 }
1525
1526 mLocked.orientedRanges.orientation.min = - M_PI_2;
1527 mLocked.orientedRanges.orientation.max = M_PI_2;
1528 mLocked.orientedRanges.orientation.flat = 0;
1529 mLocked.orientedRanges.orientation.fuzz = 0;
1530 }
Jeff Browne57e8952010-07-23 21:28:06 -07001531 }
1532
1533 if (orientationChanged || sizeChanged) {
1534 // Compute oriented surface dimensions, precision, and scales.
1535 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001536 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001537 case InputReaderPolicyInterface::ROTATION_90:
1538 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001539 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1540 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1541 mLocked.orientedXPrecision = mLocked.yPrecision;
1542 mLocked.orientedYPrecision = mLocked.xPrecision;
1543 orientedXScale = mLocked.yScale;
1544 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001545 break;
1546 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001547 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1548 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1549 mLocked.orientedXPrecision = mLocked.xPrecision;
1550 mLocked.orientedYPrecision = mLocked.yPrecision;
1551 orientedXScale = mLocked.xScale;
1552 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001553 break;
1554 }
1555
1556 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001557 mLocked.orientedRanges.x.min = 0;
1558 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1559 mLocked.orientedRanges.x.flat = 0;
1560 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001561
Jeff Brownb51719b2010-07-29 18:18:33 -07001562 mLocked.orientedRanges.y.min = 0;
1563 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1564 mLocked.orientedRanges.y.flat = 0;
1565 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001566 }
1567
Jeff Browna665ca82010-09-08 11:49:43 -07001568 if (sizeChanged) {
1569 logMotionRangesLocked();
1570 }
1571
Jeff Browne57e8952010-07-23 21:28:06 -07001572 return true;
1573}
1574
Jeff Browna665ca82010-09-08 11:49:43 -07001575static void logMotionRangeInfo(InputDeviceInfo::MotionRange* range, const char* name) {
1576 if (range) {
1577 LOGI(INDENT "Output %s range: min=%f, max=%f, flat=%f, fuzz=%f",
1578 name, range->min, range->max, range->flat, range->fuzz);
1579 } else {
1580 LOGI(INDENT "Output %s range: unsupported", name);
1581 }
1582}
1583
1584void TouchInputMapper::logMotionRangesLocked() {
1585 logMotionRangeInfo(& mLocked.orientedRanges.x, "x");
1586 logMotionRangeInfo(& mLocked.orientedRanges.y, "y");
1587 logMotionRangeInfo(mLocked.orientedRanges.havePressure
1588 ? & mLocked.orientedRanges.pressure : NULL, "pressure");
1589 logMotionRangeInfo(mLocked.orientedRanges.haveSize
1590 ? & mLocked.orientedRanges.size : NULL, "size");
1591 logMotionRangeInfo(mLocked.orientedRanges.haveTouchArea
1592 ? & mLocked.orientedRanges.touchMajor : NULL, "touchMajor");
1593 logMotionRangeInfo(mLocked.orientedRanges.haveTouchArea
1594 ? & mLocked.orientedRanges.touchMinor : NULL, "touchMinor");
1595 logMotionRangeInfo(mLocked.orientedRanges.haveToolArea
1596 ? & mLocked.orientedRanges.toolMajor : NULL, "toolMajor");
1597 logMotionRangeInfo(mLocked.orientedRanges.haveToolArea
1598 ? & mLocked.orientedRanges.toolMinor : NULL, "toolMinor");
1599 logMotionRangeInfo(mLocked.orientedRanges.haveOrientation
1600 ? & mLocked.orientedRanges.orientation : NULL, "orientation");
1601}
1602
Jeff Brownb51719b2010-07-29 18:18:33 -07001603void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001604 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001605
Jeff Brownb51719b2010-07-29 18:18:33 -07001606 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001607 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001608 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1609
Jeff Brownb51719b2010-07-29 18:18:33 -07001610 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001611
Jeff Brownb51719b2010-07-29 18:18:33 -07001612 if (virtualKeyDefinitions.size() == 0) {
1613 return;
1614 }
Jeff Browne57e8952010-07-23 21:28:06 -07001615
Jeff Brownb51719b2010-07-29 18:18:33 -07001616 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1617
Jeff Brown38a7fab2010-08-30 03:02:23 -07001618 int32_t touchScreenLeft = mRawAxes.x.minValue;
1619 int32_t touchScreenTop = mRawAxes.y.minValue;
1620 int32_t touchScreenWidth = mRawAxes.x.getRange();
1621 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001622
1623 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001624 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001625 virtualKeyDefinitions[i];
1626
1627 mLocked.virtualKeys.add();
1628 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1629
1630 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1631 int32_t keyCode;
1632 uint32_t flags;
1633 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1634 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001635 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1636 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001637 mLocked.virtualKeys.pop(); // drop the key
1638 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001639 }
1640
Jeff Brownb51719b2010-07-29 18:18:33 -07001641 virtualKey.keyCode = keyCode;
1642 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001643
Jeff Brownb51719b2010-07-29 18:18:33 -07001644 // convert the key definition's display coordinates into touch coordinates for a hit box
1645 int32_t halfWidth = virtualKeyDefinition.width / 2;
1646 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001647
Jeff Brownb51719b2010-07-29 18:18:33 -07001648 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1649 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1650 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1651 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1652 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1653 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1654 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1655 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001656
Jeff Brown38a7fab2010-08-30 03:02:23 -07001657 LOGI(INDENT "VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
Jeff Brownb51719b2010-07-29 18:18:33 -07001658 virtualKey.scanCode, virtualKey.keyCode,
1659 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1660 }
Jeff Browne57e8952010-07-23 21:28:06 -07001661}
1662
Jeff Brown38a7fab2010-08-30 03:02:23 -07001663void TouchInputMapper::parseCalibration() {
1664 const InputDeviceCalibration& in = getDevice()->getCalibration();
1665 Calibration& out = mCalibration;
1666
1667 // Touch Area
1668 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT;
1669 String8 touchAreaCalibrationString;
1670 if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) {
1671 if (touchAreaCalibrationString == "none") {
1672 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1673 } else if (touchAreaCalibrationString == "geometric") {
1674 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC;
1675 } else if (touchAreaCalibrationString == "pressure") {
1676 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1677 } else if (touchAreaCalibrationString != "default") {
1678 LOGW("Invalid value for touch.touchArea.calibration: '%s'",
1679 touchAreaCalibrationString.string());
1680 }
1681 }
1682
1683 // Tool Area
1684 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT;
1685 String8 toolAreaCalibrationString;
1686 if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) {
1687 if (toolAreaCalibrationString == "none") {
1688 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1689 } else if (toolAreaCalibrationString == "geometric") {
1690 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC;
1691 } else if (toolAreaCalibrationString == "linear") {
1692 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1693 } else if (toolAreaCalibrationString != "default") {
1694 LOGW("Invalid value for tool.toolArea.calibration: '%s'",
1695 toolAreaCalibrationString.string());
1696 }
1697 }
1698
1699 out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"),
1700 out.toolAreaLinearScale);
1701 out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"),
1702 out.toolAreaLinearBias);
1703 out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"),
1704 out.toolAreaIsSummed);
1705
1706 // Pressure
1707 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1708 String8 pressureCalibrationString;
1709 if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) {
1710 if (pressureCalibrationString == "none") {
1711 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1712 } else if (pressureCalibrationString == "physical") {
1713 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1714 } else if (pressureCalibrationString == "amplitude") {
1715 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1716 } else if (pressureCalibrationString != "default") {
1717 LOGW("Invalid value for tool.pressure.calibration: '%s'",
1718 pressureCalibrationString.string());
1719 }
1720 }
1721
1722 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1723 String8 pressureSourceString;
1724 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1725 if (pressureSourceString == "pressure") {
1726 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1727 } else if (pressureSourceString == "touch") {
1728 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1729 } else if (pressureSourceString != "default") {
1730 LOGW("Invalid value for touch.pressure.source: '%s'",
1731 pressureSourceString.string());
1732 }
1733 }
1734
1735 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1736 out.pressureScale);
1737
1738 // Size
1739 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1740 String8 sizeCalibrationString;
1741 if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) {
1742 if (sizeCalibrationString == "none") {
1743 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1744 } else if (sizeCalibrationString == "normalized") {
1745 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1746 } else if (sizeCalibrationString != "default") {
1747 LOGW("Invalid value for tool.size.calibration: '%s'",
1748 sizeCalibrationString.string());
1749 }
1750 }
1751
1752 // Orientation
1753 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1754 String8 orientationCalibrationString;
1755 if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) {
1756 if (orientationCalibrationString == "none") {
1757 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1758 } else if (orientationCalibrationString == "interpolated") {
1759 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1760 } else if (orientationCalibrationString != "default") {
1761 LOGW("Invalid value for tool.orientation.calibration: '%s'",
1762 orientationCalibrationString.string());
1763 }
1764 }
1765}
1766
1767void TouchInputMapper::resolveCalibration() {
1768 // Pressure
1769 switch (mCalibration.pressureSource) {
1770 case Calibration::PRESSURE_SOURCE_DEFAULT:
1771 if (mRawAxes.pressure.valid) {
1772 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1773 } else if (mRawAxes.touchMajor.valid) {
1774 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1775 }
1776 break;
1777
1778 case Calibration::PRESSURE_SOURCE_PRESSURE:
1779 if (! mRawAxes.pressure.valid) {
1780 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1781 "the pressure axis is not available.");
1782 }
1783 break;
1784
1785 case Calibration::PRESSURE_SOURCE_TOUCH:
1786 if (! mRawAxes.touchMajor.valid) {
1787 LOGW("Calibration property touch.pressure.source is 'touch' but "
1788 "the touchMajor axis is not available.");
1789 }
1790 break;
1791
1792 default:
1793 break;
1794 }
1795
1796 switch (mCalibration.pressureCalibration) {
1797 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1798 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1799 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1800 } else {
1801 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1802 }
1803 break;
1804
1805 default:
1806 break;
1807 }
1808
1809 // Tool Area
1810 switch (mCalibration.toolAreaCalibration) {
1811 case Calibration::TOOL_AREA_CALIBRATION_DEFAULT:
1812 if (mRawAxes.toolMajor.valid) {
1813 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1814 } else {
1815 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1816 }
1817 break;
1818
1819 default:
1820 break;
1821 }
1822
1823 // Touch Area
1824 switch (mCalibration.touchAreaCalibration) {
1825 case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT:
1826 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
1827 && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1828 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1829 } else {
1830 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1831 }
1832 break;
1833
1834 default:
1835 break;
1836 }
1837
1838 // Size
1839 switch (mCalibration.sizeCalibration) {
1840 case Calibration::SIZE_CALIBRATION_DEFAULT:
1841 if (mRawAxes.toolMajor.valid) {
1842 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1843 } else {
1844 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1845 }
1846 break;
1847
1848 default:
1849 break;
1850 }
1851
1852 // Orientation
1853 switch (mCalibration.orientationCalibration) {
1854 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1855 if (mRawAxes.orientation.valid) {
1856 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1857 } else {
1858 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1859 }
1860 break;
1861
1862 default:
1863 break;
1864 }
1865}
1866
1867void TouchInputMapper::logCalibration() {
Jeff Browna665ca82010-09-08 11:49:43 -07001868 LOGI(INDENT "Calibration:");
1869
Jeff Brown38a7fab2010-08-30 03:02:23 -07001870 // Touch Area
1871 switch (mCalibration.touchAreaCalibration) {
1872 case Calibration::TOUCH_AREA_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001873 LOGI(INDENT INDENT "touch.touchArea.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001874 break;
1875 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
Jeff Browna665ca82010-09-08 11:49:43 -07001876 LOGI(INDENT INDENT "touch.touchArea.calibration: geometric");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001877 break;
1878 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
Jeff Browna665ca82010-09-08 11:49:43 -07001879 LOGI(INDENT INDENT "touch.touchArea.calibration: pressure");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001880 break;
1881 default:
1882 assert(false);
1883 }
1884
1885 // Tool Area
1886 switch (mCalibration.toolAreaCalibration) {
1887 case Calibration::TOOL_AREA_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001888 LOGI(INDENT INDENT "touch.toolArea.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001889 break;
1890 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
Jeff Browna665ca82010-09-08 11:49:43 -07001891 LOGI(INDENT INDENT "touch.toolArea.calibration: geometric");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001892 break;
1893 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
Jeff Browna665ca82010-09-08 11:49:43 -07001894 LOGI(INDENT INDENT "touch.toolArea.calibration: linear");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001895 break;
1896 default:
1897 assert(false);
1898 }
1899
1900 if (mCalibration.haveToolAreaLinearScale) {
Jeff Browna665ca82010-09-08 11:49:43 -07001901 LOGI(INDENT INDENT "touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001902 }
1903
1904 if (mCalibration.haveToolAreaLinearBias) {
Jeff Browna665ca82010-09-08 11:49:43 -07001905 LOGI(INDENT INDENT "touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001906 }
1907
1908 if (mCalibration.haveToolAreaIsSummed) {
Jeff Browna665ca82010-09-08 11:49:43 -07001909 LOGI(INDENT INDENT "touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001910 }
1911
1912 // Pressure
1913 switch (mCalibration.pressureCalibration) {
1914 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001915 LOGI(INDENT INDENT "touch.pressure.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001916 break;
1917 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Browna665ca82010-09-08 11:49:43 -07001918 LOGI(INDENT INDENT "touch.pressure.calibration: physical");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001919 break;
1920 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Browna665ca82010-09-08 11:49:43 -07001921 LOGI(INDENT INDENT "touch.pressure.calibration: amplitude");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001922 break;
1923 default:
1924 assert(false);
1925 }
1926
1927 switch (mCalibration.pressureSource) {
1928 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Browna665ca82010-09-08 11:49:43 -07001929 LOGI(INDENT INDENT "touch.pressure.source: pressure");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001930 break;
1931 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Browna665ca82010-09-08 11:49:43 -07001932 LOGI(INDENT INDENT "touch.pressure.source: touch");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001933 break;
1934 case Calibration::PRESSURE_SOURCE_DEFAULT:
1935 break;
1936 default:
1937 assert(false);
1938 }
1939
1940 if (mCalibration.havePressureScale) {
Jeff Browna665ca82010-09-08 11:49:43 -07001941 LOGI(INDENT INDENT "touch.pressure.scale: %f", mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001942 }
1943
1944 // Size
1945 switch (mCalibration.sizeCalibration) {
1946 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001947 LOGI(INDENT INDENT "touch.size.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001948 break;
1949 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Browna665ca82010-09-08 11:49:43 -07001950 LOGI(INDENT INDENT "touch.size.calibration: normalized");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001951 break;
1952 default:
1953 assert(false);
1954 }
1955
1956 // Orientation
1957 switch (mCalibration.orientationCalibration) {
1958 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001959 LOGI(INDENT INDENT "touch.orientation.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001960 break;
1961 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Browna665ca82010-09-08 11:49:43 -07001962 LOGI(INDENT INDENT "touch.orientation.calibration: interpolated");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001963 break;
1964 default:
1965 assert(false);
1966 }
1967}
1968
Jeff Browne57e8952010-07-23 21:28:06 -07001969void TouchInputMapper::reset() {
1970 // Synthesize touch up event if touch is currently down.
1971 // This will also take care of finishing virtual key processing if needed.
1972 if (mLastTouch.pointerCount != 0) {
1973 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1974 mCurrentTouch.clear();
1975 syncTouch(when, true);
1976 }
1977
Jeff Brownb51719b2010-07-29 18:18:33 -07001978 { // acquire lock
1979 AutoMutex _l(mLock);
1980 initializeLocked();
1981 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001982
Jeff Brownb51719b2010-07-29 18:18:33 -07001983 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001984}
1985
1986void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001987 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07001988
1989 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001990 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1991
1992 if (! applyStandardPolicyActions(when, policyActions)) {
1993 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07001994 return; // event dropped
1995 }
1996
Jeff Brownb51719b2010-07-29 18:18:33 -07001997 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07001998
Jeff Browne57e8952010-07-23 21:28:06 -07001999 if (mParameters.useBadTouchFilter) {
2000 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002001 havePointerIds = false;
2002 }
2003 }
2004
Jeff Browne57e8952010-07-23 21:28:06 -07002005 if (mParameters.useJumpyTouchFilter) {
2006 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002007 havePointerIds = false;
2008 }
2009 }
2010
2011 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002012 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002013 }
2014
Jeff Browne57e8952010-07-23 21:28:06 -07002015 TouchData temp;
2016 TouchData* savedTouch;
2017 if (mParameters.useAveragingTouchFilter) {
2018 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002019 savedTouch = & temp;
2020
Jeff Browne57e8952010-07-23 21:28:06 -07002021 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002022 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002023 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002024 }
2025
Jeff Brownb51719b2010-07-29 18:18:33 -07002026 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002027
Jeff Browne57e8952010-07-23 21:28:06 -07002028 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2029 if (touchResult == DISPATCH_TOUCH) {
2030 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002031 }
2032
Jeff Brownb51719b2010-07-29 18:18:33 -07002033 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002034
Jeff Browne57e8952010-07-23 21:28:06 -07002035 if (touchResult == DROP_STROKE) {
2036 mLastTouch.clear();
2037 } else {
2038 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002039 }
Jeff Browne839a582010-04-22 18:58:52 -07002040}
2041
Jeff Browne57e8952010-07-23 21:28:06 -07002042TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2043 nsecs_t when, uint32_t policyFlags) {
2044 int32_t keyEventAction, keyEventFlags;
2045 int32_t keyCode, scanCode, downTime;
2046 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002047
Jeff Brownb51719b2010-07-29 18:18:33 -07002048 { // acquire lock
2049 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002050
Jeff Brownb51719b2010-07-29 18:18:33 -07002051 // Update surface size and orientation, including virtual key positions.
2052 if (! configureSurfaceLocked()) {
2053 return DROP_STROKE;
2054 }
2055
2056 // Check for virtual key press.
2057 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002058 if (mCurrentTouch.pointerCount == 0) {
2059 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002060 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002061#if DEBUG_VIRTUAL_KEYS
2062 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2063 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2064#endif
2065 keyEventAction = AKEY_EVENT_ACTION_UP;
2066 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2067 touchResult = SKIP_TOUCH;
2068 goto DispatchVirtualKey;
2069 }
2070
2071 if (mCurrentTouch.pointerCount == 1) {
2072 int32_t x = mCurrentTouch.pointers[0].x;
2073 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002074 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2075 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002076 // Pointer is still within the space of the virtual key.
2077 return SKIP_TOUCH;
2078 }
2079 }
2080
2081 // Pointer left virtual key area or another pointer also went down.
2082 // Send key cancellation and drop the stroke so subsequent motions will be
2083 // considered fresh downs. This is useful when the user swipes away from the
2084 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002085 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002086#if DEBUG_VIRTUAL_KEYS
2087 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2088 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2089#endif
2090 keyEventAction = AKEY_EVENT_ACTION_UP;
2091 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2092 | AKEY_EVENT_FLAG_CANCELED;
2093 touchResult = DROP_STROKE;
2094 goto DispatchVirtualKey;
2095 } else {
2096 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2097 // Pointer just went down. Handle off-screen touches, if needed.
2098 int32_t x = mCurrentTouch.pointers[0].x;
2099 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002100 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002101 // If exactly one pointer went down, check for virtual key hit.
2102 // Otherwise we will drop the entire stroke.
2103 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002104 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002105 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002106 mLocked.currentVirtualKey.down = true;
2107 mLocked.currentVirtualKey.downTime = when;
2108 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2109 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002110#if DEBUG_VIRTUAL_KEYS
2111 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2112 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2113#endif
2114 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2115 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2116 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2117 touchResult = SKIP_TOUCH;
2118 goto DispatchVirtualKey;
2119 }
2120 }
2121 return DROP_STROKE;
2122 }
2123 }
2124 return DISPATCH_TOUCH;
2125 }
2126
2127 DispatchVirtualKey:
2128 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002129 keyCode = mLocked.currentVirtualKey.keyCode;
2130 scanCode = mLocked.currentVirtualKey.scanCode;
2131 downTime = mLocked.currentVirtualKey.downTime;
2132 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002133
2134 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002135 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
2136 keyCode, scanCode, downTime);
2137 return touchResult;
2138}
2139
2140void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
2141 int32_t keyEventAction, int32_t keyEventFlags,
2142 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07002143 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07002144
Jeff Brown5c1ed842010-07-14 18:48:53 -07002145 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Browne57e8952010-07-23 21:28:06 -07002146 getPolicy()->virtualKeyDownFeedback();
Jeff Brownf16c26d2010-07-02 15:37:36 -07002147 }
Jeff Browne839a582010-04-22 18:58:52 -07002148
Jeff Browne57e8952010-07-23 21:28:06 -07002149 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002150 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07002151
Jeff Browne57e8952010-07-23 21:28:06 -07002152 if (applyStandardPolicyActions(when, policyActions)) {
2153 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07002154 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2155 }
Jeff Browne839a582010-04-22 18:58:52 -07002156}
2157
Jeff Browne57e8952010-07-23 21:28:06 -07002158void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2159 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2160 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002161 if (currentPointerCount == 0 && lastPointerCount == 0) {
2162 return; // nothing to do!
2163 }
2164
Jeff Browne57e8952010-07-23 21:28:06 -07002165 BitSet32 currentIdBits = mCurrentTouch.idBits;
2166 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002167
2168 if (currentIdBits == lastIdBits) {
2169 // No pointer id changes so this is a move event.
2170 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002171 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002172 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002173 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002174 } else {
2175 // There may be pointers going up and pointers going down at the same time when pointer
2176 // ids are reported by the device driver.
2177 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2178 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2179 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002180 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002181
2182 while (! upIdBits.isEmpty()) {
2183 uint32_t upId = upIdBits.firstMarkedBit();
2184 upIdBits.clearBit(upId);
2185 BitSet32 oldActiveIdBits = activeIdBits;
2186 activeIdBits.clearBit(upId);
2187
2188 int32_t motionEventAction;
2189 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002190 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002191 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002192 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002193 }
2194
Jeff Browne57e8952010-07-23 21:28:06 -07002195 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002196 oldActiveIdBits, upId, pointerCount, motionEventAction);
2197 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002198 }
2199
2200 while (! downIdBits.isEmpty()) {
2201 uint32_t downId = downIdBits.firstMarkedBit();
2202 downIdBits.clearBit(downId);
2203 BitSet32 oldActiveIdBits = activeIdBits;
2204 activeIdBits.markBit(downId);
2205
2206 int32_t motionEventAction;
2207 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002208 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002209 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002210 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002211 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002212 }
2213
Jeff Brown38a7fab2010-08-30 03:02:23 -07002214 pointerCount += 1;
Jeff Browne57e8952010-07-23 21:28:06 -07002215 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002216 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002217 }
2218 }
2219}
2220
Jeff Browne57e8952010-07-23 21:28:06 -07002221void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002222 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002223 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002224 int32_t pointerIds[MAX_POINTERS];
2225 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002226 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002227 float xPrecision, yPrecision;
2228
2229 { // acquire lock
2230 AutoMutex _l(mLock);
2231
2232 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2233 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002234 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002235 uint32_t id = idBits.firstMarkedBit();
2236 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002237 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002238
Jeff Brown38a7fab2010-08-30 03:02:23 -07002239 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002240
Jeff Brown38a7fab2010-08-30 03:02:23 -07002241 // X and Y
2242 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2243 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002244
Jeff Brown38a7fab2010-08-30 03:02:23 -07002245 // ToolMajor and ToolMinor
2246 float toolMajor, toolMinor;
2247 switch (mCalibration.toolAreaCalibration) {
2248 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
2249 toolMajor = in.toolMajor * mLocked.geometricScale;
2250 if (mRawAxes.toolMinor.valid) {
2251 toolMinor = in.toolMinor * mLocked.geometricScale;
2252 } else {
2253 toolMinor = toolMajor;
2254 }
2255 break;
2256 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
2257 toolMajor = in.toolMajor != 0
2258 ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias
2259 : 0;
2260 if (mRawAxes.toolMinor.valid) {
2261 toolMinor = in.toolMinor != 0
2262 ? in.toolMinor * mLocked.toolAreaLinearScale
2263 + mLocked.toolAreaLinearBias
2264 : 0;
2265 } else {
2266 toolMinor = toolMajor;
2267 }
2268 break;
2269 default:
2270 toolMajor = 0;
2271 toolMinor = 0;
2272 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002273 }
2274
Jeff Brown38a7fab2010-08-30 03:02:23 -07002275 if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) {
2276 toolMajor /= pointerCount;
2277 toolMinor /= pointerCount;
2278 }
2279
2280 // Pressure
2281 float rawPressure;
2282 switch (mCalibration.pressureSource) {
2283 case Calibration::PRESSURE_SOURCE_PRESSURE:
2284 rawPressure = in.pressure;
2285 break;
2286 case Calibration::PRESSURE_SOURCE_TOUCH:
2287 rawPressure = in.touchMajor;
2288 break;
2289 default:
2290 rawPressure = 0;
2291 }
2292
2293 float pressure;
2294 switch (mCalibration.pressureCalibration) {
2295 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2296 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2297 pressure = rawPressure * mLocked.pressureScale;
2298 break;
2299 default:
2300 pressure = 1;
2301 break;
2302 }
2303
2304 // TouchMajor and TouchMinor
2305 float touchMajor, touchMinor;
2306 switch (mCalibration.touchAreaCalibration) {
2307 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
2308 touchMajor = in.touchMajor * mLocked.geometricScale;
2309 if (mRawAxes.touchMinor.valid) {
2310 touchMinor = in.touchMinor * mLocked.geometricScale;
2311 } else {
2312 touchMinor = touchMajor;
2313 }
2314 break;
2315 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
2316 touchMajor = toolMajor * pressure;
2317 touchMinor = toolMinor * pressure;
2318 break;
2319 default:
2320 touchMajor = 0;
2321 touchMinor = 0;
2322 break;
2323 }
2324
2325 if (touchMajor > toolMajor) {
2326 touchMajor = toolMajor;
2327 }
2328 if (touchMinor > toolMinor) {
2329 touchMinor = toolMinor;
2330 }
2331
2332 // Size
2333 float size;
2334 switch (mCalibration.sizeCalibration) {
2335 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2336 float rawSize = mRawAxes.toolMinor.valid
2337 ? avg(in.toolMajor, in.toolMinor)
2338 : in.toolMajor;
2339 size = rawSize * mLocked.sizeScale;
2340 break;
2341 }
2342 default:
2343 size = 0;
2344 break;
2345 }
2346
2347 // Orientation
2348 float orientation;
2349 switch (mCalibration.orientationCalibration) {
2350 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2351 orientation = in.orientation * mLocked.orientationScale;
2352 break;
2353 default:
2354 orientation = 0;
2355 }
2356
2357 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002358 switch (mLocked.surfaceOrientation) {
2359 case InputReaderPolicyInterface::ROTATION_90: {
2360 float xTemp = x;
2361 x = y;
2362 y = mLocked.surfaceWidth - xTemp;
2363 orientation -= M_PI_2;
2364 if (orientation < - M_PI_2) {
2365 orientation += M_PI;
2366 }
2367 break;
2368 }
2369 case InputReaderPolicyInterface::ROTATION_180: {
2370 x = mLocked.surfaceWidth - x;
2371 y = mLocked.surfaceHeight - y;
2372 orientation = - orientation;
2373 break;
2374 }
2375 case InputReaderPolicyInterface::ROTATION_270: {
2376 float xTemp = x;
2377 x = mLocked.surfaceHeight - y;
2378 y = xTemp;
2379 orientation += M_PI_2;
2380 if (orientation > M_PI_2) {
2381 orientation -= M_PI;
2382 }
2383 break;
2384 }
2385 }
2386
Jeff Brown38a7fab2010-08-30 03:02:23 -07002387 // Write output coords.
2388 PointerCoords& out = pointerCoords[outIndex];
2389 out.x = x;
2390 out.y = y;
2391 out.pressure = pressure;
2392 out.size = size;
2393 out.touchMajor = touchMajor;
2394 out.touchMinor = touchMinor;
2395 out.toolMajor = toolMajor;
2396 out.toolMinor = toolMinor;
2397 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002398
Jeff Brown38a7fab2010-08-30 03:02:23 -07002399 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002400
2401 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002402 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002403 }
Jeff Browne839a582010-04-22 18:58:52 -07002404 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002405
2406 // Check edge flags by looking only at the first pointer since the flags are
2407 // global to the event.
2408 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2409 if (pointerCoords[0].x <= 0) {
2410 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2411 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2412 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2413 }
2414 if (pointerCoords[0].y <= 0) {
2415 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2416 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2417 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2418 }
Jeff Browne839a582010-04-22 18:58:52 -07002419 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002420
2421 xPrecision = mLocked.orientedXPrecision;
2422 yPrecision = mLocked.orientedYPrecision;
2423 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002424
Jeff Browne57e8952010-07-23 21:28:06 -07002425 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002426 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002427 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002428 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002429}
2430
Jeff Brownb51719b2010-07-29 18:18:33 -07002431bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002432 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2433 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2434 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002435 }
Jeff Browne57e8952010-07-23 21:28:06 -07002436 return true;
2437}
2438
Jeff Brownb51719b2010-07-29 18:18:33 -07002439const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2440 int32_t x, int32_t y) {
2441 size_t numVirtualKeys = mLocked.virtualKeys.size();
2442 for (size_t i = 0; i < numVirtualKeys; i++) {
2443 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002444
2445#if DEBUG_VIRTUAL_KEYS
2446 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2447 "left=%d, top=%d, right=%d, bottom=%d",
2448 x, y,
2449 virtualKey.keyCode, virtualKey.scanCode,
2450 virtualKey.hitLeft, virtualKey.hitTop,
2451 virtualKey.hitRight, virtualKey.hitBottom);
2452#endif
2453
2454 if (virtualKey.isHit(x, y)) {
2455 return & virtualKey;
2456 }
2457 }
2458
2459 return NULL;
2460}
2461
2462void TouchInputMapper::calculatePointerIds() {
2463 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2464 uint32_t lastPointerCount = mLastTouch.pointerCount;
2465
2466 if (currentPointerCount == 0) {
2467 // No pointers to assign.
2468 mCurrentTouch.idBits.clear();
2469 } else if (lastPointerCount == 0) {
2470 // All pointers are new.
2471 mCurrentTouch.idBits.clear();
2472 for (uint32_t i = 0; i < currentPointerCount; i++) {
2473 mCurrentTouch.pointers[i].id = i;
2474 mCurrentTouch.idToIndex[i] = i;
2475 mCurrentTouch.idBits.markBit(i);
2476 }
2477 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2478 // Only one pointer and no change in count so it must have the same id as before.
2479 uint32_t id = mLastTouch.pointers[0].id;
2480 mCurrentTouch.pointers[0].id = id;
2481 mCurrentTouch.idToIndex[id] = 0;
2482 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2483 } else {
2484 // General case.
2485 // We build a heap of squared euclidean distances between current and last pointers
2486 // associated with the current and last pointer indices. Then, we find the best
2487 // match (by distance) for each current pointer.
2488 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2489
2490 uint32_t heapSize = 0;
2491 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2492 currentPointerIndex++) {
2493 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2494 lastPointerIndex++) {
2495 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2496 - mLastTouch.pointers[lastPointerIndex].x;
2497 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2498 - mLastTouch.pointers[lastPointerIndex].y;
2499
2500 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2501
2502 // Insert new element into the heap (sift up).
2503 heap[heapSize].currentPointerIndex = currentPointerIndex;
2504 heap[heapSize].lastPointerIndex = lastPointerIndex;
2505 heap[heapSize].distance = distance;
2506 heapSize += 1;
2507 }
2508 }
2509
2510 // Heapify
2511 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2512 startIndex -= 1;
2513 for (uint32_t parentIndex = startIndex; ;) {
2514 uint32_t childIndex = parentIndex * 2 + 1;
2515 if (childIndex >= heapSize) {
2516 break;
2517 }
2518
2519 if (childIndex + 1 < heapSize
2520 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2521 childIndex += 1;
2522 }
2523
2524 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2525 break;
2526 }
2527
2528 swap(heap[parentIndex], heap[childIndex]);
2529 parentIndex = childIndex;
2530 }
2531 }
2532
2533#if DEBUG_POINTER_ASSIGNMENT
2534 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2535 for (size_t i = 0; i < heapSize; i++) {
2536 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2537 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2538 heap[i].distance);
2539 }
2540#endif
2541
2542 // Pull matches out by increasing order of distance.
2543 // To avoid reassigning pointers that have already been matched, the loop keeps track
2544 // of which last and current pointers have been matched using the matchedXXXBits variables.
2545 // It also tracks the used pointer id bits.
2546 BitSet32 matchedLastBits(0);
2547 BitSet32 matchedCurrentBits(0);
2548 BitSet32 usedIdBits(0);
2549 bool first = true;
2550 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2551 for (;;) {
2552 if (first) {
2553 // The first time through the loop, we just consume the root element of
2554 // the heap (the one with smallest distance).
2555 first = false;
2556 } else {
2557 // Previous iterations consumed the root element of the heap.
2558 // Pop root element off of the heap (sift down).
2559 heapSize -= 1;
2560 assert(heapSize > 0);
2561
2562 // Sift down.
2563 heap[0] = heap[heapSize];
2564 for (uint32_t parentIndex = 0; ;) {
2565 uint32_t childIndex = parentIndex * 2 + 1;
2566 if (childIndex >= heapSize) {
2567 break;
2568 }
2569
2570 if (childIndex + 1 < heapSize
2571 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2572 childIndex += 1;
2573 }
2574
2575 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2576 break;
2577 }
2578
2579 swap(heap[parentIndex], heap[childIndex]);
2580 parentIndex = childIndex;
2581 }
2582
2583#if DEBUG_POINTER_ASSIGNMENT
2584 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2585 for (size_t i = 0; i < heapSize; i++) {
2586 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2587 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2588 heap[i].distance);
2589 }
2590#endif
2591 }
2592
2593 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2594 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2595
2596 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2597 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2598
2599 matchedCurrentBits.markBit(currentPointerIndex);
2600 matchedLastBits.markBit(lastPointerIndex);
2601
2602 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2603 mCurrentTouch.pointers[currentPointerIndex].id = id;
2604 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2605 usedIdBits.markBit(id);
2606
2607#if DEBUG_POINTER_ASSIGNMENT
2608 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2609 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2610#endif
2611 break;
2612 }
2613 }
2614
2615 // Assign fresh ids to new pointers.
2616 if (currentPointerCount > lastPointerCount) {
2617 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2618 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2619 uint32_t id = usedIdBits.firstUnmarkedBit();
2620
2621 mCurrentTouch.pointers[currentPointerIndex].id = id;
2622 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2623 usedIdBits.markBit(id);
2624
2625#if DEBUG_POINTER_ASSIGNMENT
2626 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2627 currentPointerIndex, id);
2628#endif
2629
2630 if (--i == 0) break; // done
2631 matchedCurrentBits.markBit(currentPointerIndex);
2632 }
2633 }
2634
2635 // Fix id bits.
2636 mCurrentTouch.idBits = usedIdBits;
2637 }
2638}
2639
2640/* Special hack for devices that have bad screen data: if one of the
2641 * points has moved more than a screen height from the last position,
2642 * then drop it. */
2643bool TouchInputMapper::applyBadTouchFilter() {
2644 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002645 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002646 return false;
2647 }
2648
2649 uint32_t pointerCount = mCurrentTouch.pointerCount;
2650
2651 // Nothing to do if there are no points.
2652 if (pointerCount == 0) {
2653 return false;
2654 }
2655
2656 // Don't do anything if a finger is going down or up. We run
2657 // here before assigning pointer IDs, so there isn't a good
2658 // way to do per-finger matching.
2659 if (pointerCount != mLastTouch.pointerCount) {
2660 return false;
2661 }
2662
2663 // We consider a single movement across more than a 7/16 of
2664 // the long size of the screen to be bad. This was a magic value
2665 // determined by looking at the maximum distance it is feasible
2666 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002667 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002668
2669 // XXX The original code in InputDevice.java included commented out
2670 // code for testing the X axis. Note that when we drop a point
2671 // we don't actually restore the old X either. Strange.
2672 // The old code also tries to track when bad points were previously
2673 // detected but it turns out that due to the placement of a "break"
2674 // at the end of the loop, we never set mDroppedBadPoint to true
2675 // so it is effectively dead code.
2676 // Need to figure out if the old code is busted or just overcomplicated
2677 // but working as intended.
2678
2679 // Look through all new points and see if any are farther than
2680 // acceptable from all previous points.
2681 for (uint32_t i = pointerCount; i-- > 0; ) {
2682 int32_t y = mCurrentTouch.pointers[i].y;
2683 int32_t closestY = INT_MAX;
2684 int32_t closestDeltaY = 0;
2685
2686#if DEBUG_HACKS
2687 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2688#endif
2689
2690 for (uint32_t j = pointerCount; j-- > 0; ) {
2691 int32_t lastY = mLastTouch.pointers[j].y;
2692 int32_t deltaY = abs(y - lastY);
2693
2694#if DEBUG_HACKS
2695 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2696 j, lastY, deltaY);
2697#endif
2698
2699 if (deltaY < maxDeltaY) {
2700 goto SkipSufficientlyClosePoint;
2701 }
2702 if (deltaY < closestDeltaY) {
2703 closestDeltaY = deltaY;
2704 closestY = lastY;
2705 }
2706 }
2707
2708 // Must not have found a close enough match.
2709#if DEBUG_HACKS
2710 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2711 i, y, closestY, closestDeltaY, maxDeltaY);
2712#endif
2713
2714 mCurrentTouch.pointers[i].y = closestY;
2715 return true; // XXX original code only corrects one point
2716
2717 SkipSufficientlyClosePoint: ;
2718 }
2719
2720 // No change.
2721 return false;
2722}
2723
2724/* Special hack for devices that have bad screen data: drop points where
2725 * the coordinate value for one axis has jumped to the other pointer's location.
2726 */
2727bool TouchInputMapper::applyJumpyTouchFilter() {
2728 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002729 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002730 return false;
2731 }
2732
2733 uint32_t pointerCount = mCurrentTouch.pointerCount;
2734 if (mLastTouch.pointerCount != pointerCount) {
2735#if DEBUG_HACKS
2736 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2737 mLastTouch.pointerCount, pointerCount);
2738 for (uint32_t i = 0; i < pointerCount; i++) {
2739 LOGD(" Pointer %d (%d, %d)", i,
2740 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2741 }
2742#endif
2743
2744 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2745 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2746 // Just drop the first few events going from 1 to 2 pointers.
2747 // They're bad often enough that they're not worth considering.
2748 mCurrentTouch.pointerCount = 1;
2749 mJumpyTouchFilter.jumpyPointsDropped += 1;
2750
2751#if DEBUG_HACKS
2752 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2753#endif
2754 return true;
2755 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2756 // The event when we go from 2 -> 1 tends to be messed up too
2757 mCurrentTouch.pointerCount = 2;
2758 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2759 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2760 mJumpyTouchFilter.jumpyPointsDropped += 1;
2761
2762#if DEBUG_HACKS
2763 for (int32_t i = 0; i < 2; i++) {
2764 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2765 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2766 }
2767#endif
2768 return true;
2769 }
2770 }
2771 // Reset jumpy points dropped on other transitions or if limit exceeded.
2772 mJumpyTouchFilter.jumpyPointsDropped = 0;
2773
2774#if DEBUG_HACKS
2775 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2776#endif
2777 return false;
2778 }
2779
2780 // We have the same number of pointers as last time.
2781 // A 'jumpy' point is one where the coordinate value for one axis
2782 // has jumped to the other pointer's location. No need to do anything
2783 // else if we only have one pointer.
2784 if (pointerCount < 2) {
2785 return false;
2786 }
2787
2788 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002789 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002790
2791 // We only replace the single worst jumpy point as characterized by pointer distance
2792 // in a single axis.
2793 int32_t badPointerIndex = -1;
2794 int32_t badPointerReplacementIndex = -1;
2795 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2796
2797 for (uint32_t i = pointerCount; i-- > 0; ) {
2798 int32_t x = mCurrentTouch.pointers[i].x;
2799 int32_t y = mCurrentTouch.pointers[i].y;
2800
2801#if DEBUG_HACKS
2802 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2803#endif
2804
2805 // Check if a touch point is too close to another's coordinates
2806 bool dropX = false, dropY = false;
2807 for (uint32_t j = 0; j < pointerCount; j++) {
2808 if (i == j) {
2809 continue;
2810 }
2811
2812 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2813 dropX = true;
2814 break;
2815 }
2816
2817 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2818 dropY = true;
2819 break;
2820 }
2821 }
2822 if (! dropX && ! dropY) {
2823 continue; // not jumpy
2824 }
2825
2826 // Find a replacement candidate by comparing with older points on the
2827 // complementary (non-jumpy) axis.
2828 int32_t distance = INT_MIN; // distance to be corrected
2829 int32_t replacementIndex = -1;
2830
2831 if (dropX) {
2832 // X looks too close. Find an older replacement point with a close Y.
2833 int32_t smallestDeltaY = INT_MAX;
2834 for (uint32_t j = 0; j < pointerCount; j++) {
2835 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2836 if (deltaY < smallestDeltaY) {
2837 smallestDeltaY = deltaY;
2838 replacementIndex = j;
2839 }
2840 }
2841 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2842 } else {
2843 // Y looks too close. Find an older replacement point with a close X.
2844 int32_t smallestDeltaX = INT_MAX;
2845 for (uint32_t j = 0; j < pointerCount; j++) {
2846 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2847 if (deltaX < smallestDeltaX) {
2848 smallestDeltaX = deltaX;
2849 replacementIndex = j;
2850 }
2851 }
2852 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2853 }
2854
2855 // If replacing this pointer would correct a worse error than the previous ones
2856 // considered, then use this replacement instead.
2857 if (distance > badPointerDistance) {
2858 badPointerIndex = i;
2859 badPointerReplacementIndex = replacementIndex;
2860 badPointerDistance = distance;
2861 }
2862 }
2863
2864 // Correct the jumpy pointer if one was found.
2865 if (badPointerIndex >= 0) {
2866#if DEBUG_HACKS
2867 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2868 badPointerIndex,
2869 mLastTouch.pointers[badPointerReplacementIndex].x,
2870 mLastTouch.pointers[badPointerReplacementIndex].y);
2871#endif
2872
2873 mCurrentTouch.pointers[badPointerIndex].x =
2874 mLastTouch.pointers[badPointerReplacementIndex].x;
2875 mCurrentTouch.pointers[badPointerIndex].y =
2876 mLastTouch.pointers[badPointerReplacementIndex].y;
2877 mJumpyTouchFilter.jumpyPointsDropped += 1;
2878 return true;
2879 }
2880 }
2881
2882 mJumpyTouchFilter.jumpyPointsDropped = 0;
2883 return false;
2884}
2885
2886/* Special hack for devices that have bad screen data: aggregate and
2887 * compute averages of the coordinate data, to reduce the amount of
2888 * jitter seen by applications. */
2889void TouchInputMapper::applyAveragingTouchFilter() {
2890 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2891 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2892 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2893 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002894 int32_t pressure;
2895 switch (mCalibration.pressureSource) {
2896 case Calibration::PRESSURE_SOURCE_PRESSURE:
2897 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2898 break;
2899 case Calibration::PRESSURE_SOURCE_TOUCH:
2900 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2901 break;
2902 default:
2903 pressure = 1;
2904 break;
2905 }
Jeff Browne57e8952010-07-23 21:28:06 -07002906
2907 if (mLastTouch.idBits.hasBit(id)) {
2908 // Pointer was down before and is still down now.
2909 // Compute average over history trace.
2910 uint32_t start = mAveragingTouchFilter.historyStart[id];
2911 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2912
2913 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2914 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2915 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2916
2917#if DEBUG_HACKS
2918 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2919 id, distance);
2920#endif
2921
2922 if (distance < AVERAGING_DISTANCE_LIMIT) {
2923 // Increment end index in preparation for recording new historical data.
2924 end += 1;
2925 if (end > AVERAGING_HISTORY_SIZE) {
2926 end = 0;
2927 }
2928
2929 // If the end index has looped back to the start index then we have filled
2930 // the historical trace up to the desired size so we drop the historical
2931 // data at the start of the trace.
2932 if (end == start) {
2933 start += 1;
2934 if (start > AVERAGING_HISTORY_SIZE) {
2935 start = 0;
2936 }
2937 }
2938
2939 // Add the raw data to the historical trace.
2940 mAveragingTouchFilter.historyStart[id] = start;
2941 mAveragingTouchFilter.historyEnd[id] = end;
2942 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2943 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2944 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2945
2946 // Average over all historical positions in the trace by total pressure.
2947 int32_t averagedX = 0;
2948 int32_t averagedY = 0;
2949 int32_t totalPressure = 0;
2950 for (;;) {
2951 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2952 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2953 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2954 .pointers[id].pressure;
2955
2956 averagedX += historicalX * historicalPressure;
2957 averagedY += historicalY * historicalPressure;
2958 totalPressure += historicalPressure;
2959
2960 if (start == end) {
2961 break;
2962 }
2963
2964 start += 1;
2965 if (start > AVERAGING_HISTORY_SIZE) {
2966 start = 0;
2967 }
2968 }
2969
Jeff Brown38a7fab2010-08-30 03:02:23 -07002970 if (totalPressure != 0) {
2971 averagedX /= totalPressure;
2972 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07002973
2974#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07002975 LOGD("AveragingTouchFilter: Pointer id %d - "
2976 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2977 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07002978#endif
2979
Jeff Brown38a7fab2010-08-30 03:02:23 -07002980 mCurrentTouch.pointers[currentIndex].x = averagedX;
2981 mCurrentTouch.pointers[currentIndex].y = averagedY;
2982 }
Jeff Browne57e8952010-07-23 21:28:06 -07002983 } else {
2984#if DEBUG_HACKS
2985 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2986#endif
2987 }
2988 } else {
2989#if DEBUG_HACKS
2990 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2991#endif
2992 }
2993
2994 // Reset pointer history.
2995 mAveragingTouchFilter.historyStart[id] = 0;
2996 mAveragingTouchFilter.historyEnd[id] = 0;
2997 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2998 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2999 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3000 }
3001}
3002
3003int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003004 { // acquire lock
3005 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003006
Jeff Brownb51719b2010-07-29 18:18:33 -07003007 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003008 return AKEY_STATE_VIRTUAL;
3009 }
3010
Jeff Brownb51719b2010-07-29 18:18:33 -07003011 size_t numVirtualKeys = mLocked.virtualKeys.size();
3012 for (size_t i = 0; i < numVirtualKeys; i++) {
3013 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003014 if (virtualKey.keyCode == keyCode) {
3015 return AKEY_STATE_UP;
3016 }
3017 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003018 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003019
3020 return AKEY_STATE_UNKNOWN;
3021}
3022
3023int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003024 { // acquire lock
3025 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003026
Jeff Brownb51719b2010-07-29 18:18:33 -07003027 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003028 return AKEY_STATE_VIRTUAL;
3029 }
3030
Jeff Brownb51719b2010-07-29 18:18:33 -07003031 size_t numVirtualKeys = mLocked.virtualKeys.size();
3032 for (size_t i = 0; i < numVirtualKeys; i++) {
3033 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003034 if (virtualKey.scanCode == scanCode) {
3035 return AKEY_STATE_UP;
3036 }
3037 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003038 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003039
3040 return AKEY_STATE_UNKNOWN;
3041}
3042
3043bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3044 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003045 { // acquire lock
3046 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003047
Jeff Brownb51719b2010-07-29 18:18:33 -07003048 size_t numVirtualKeys = mLocked.virtualKeys.size();
3049 for (size_t i = 0; i < numVirtualKeys; i++) {
3050 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003051
3052 for (size_t i = 0; i < numCodes; i++) {
3053 if (virtualKey.keyCode == keyCodes[i]) {
3054 outFlags[i] = 1;
3055 }
3056 }
3057 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003058 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003059
3060 return true;
3061}
3062
3063
3064// --- SingleTouchInputMapper ---
3065
3066SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3067 TouchInputMapper(device, associatedDisplayId) {
3068 initialize();
3069}
3070
3071SingleTouchInputMapper::~SingleTouchInputMapper() {
3072}
3073
3074void SingleTouchInputMapper::initialize() {
3075 mAccumulator.clear();
3076
3077 mDown = false;
3078 mX = 0;
3079 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003080 mPressure = 0; // default to 0 for devices that don't report pressure
3081 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003082}
3083
3084void SingleTouchInputMapper::reset() {
3085 TouchInputMapper::reset();
3086
Jeff Browne57e8952010-07-23 21:28:06 -07003087 initialize();
3088 }
3089
3090void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3091 switch (rawEvent->type) {
3092 case EV_KEY:
3093 switch (rawEvent->scanCode) {
3094 case BTN_TOUCH:
3095 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3096 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003097 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3098 // not have received valid position information yet. This logic assumes that
3099 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003100 break;
3101 }
3102 break;
3103
3104 case EV_ABS:
3105 switch (rawEvent->scanCode) {
3106 case ABS_X:
3107 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3108 mAccumulator.absX = rawEvent->value;
3109 break;
3110 case ABS_Y:
3111 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3112 mAccumulator.absY = rawEvent->value;
3113 break;
3114 case ABS_PRESSURE:
3115 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3116 mAccumulator.absPressure = rawEvent->value;
3117 break;
3118 case ABS_TOOL_WIDTH:
3119 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3120 mAccumulator.absToolWidth = rawEvent->value;
3121 break;
3122 }
3123 break;
3124
3125 case EV_SYN:
3126 switch (rawEvent->scanCode) {
3127 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003128 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003129 break;
3130 }
3131 break;
3132 }
3133}
3134
3135void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003136 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003137 if (fields == 0) {
3138 return; // no new state changes, so nothing to do
3139 }
Jeff Browne57e8952010-07-23 21:28:06 -07003140
3141 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3142 mDown = mAccumulator.btnTouch;
3143 }
3144
3145 if (fields & Accumulator::FIELD_ABS_X) {
3146 mX = mAccumulator.absX;
3147 }
3148
3149 if (fields & Accumulator::FIELD_ABS_Y) {
3150 mY = mAccumulator.absY;
3151 }
3152
3153 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3154 mPressure = mAccumulator.absPressure;
3155 }
3156
3157 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003158 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003159 }
3160
3161 mCurrentTouch.clear();
3162
3163 if (mDown) {
3164 mCurrentTouch.pointerCount = 1;
3165 mCurrentTouch.pointers[0].id = 0;
3166 mCurrentTouch.pointers[0].x = mX;
3167 mCurrentTouch.pointers[0].y = mY;
3168 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003169 mCurrentTouch.pointers[0].touchMajor = 0;
3170 mCurrentTouch.pointers[0].touchMinor = 0;
3171 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3172 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003173 mCurrentTouch.pointers[0].orientation = 0;
3174 mCurrentTouch.idToIndex[0] = 0;
3175 mCurrentTouch.idBits.markBit(0);
3176 }
3177
3178 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003179
3180 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003181}
3182
Jeff Brown38a7fab2010-08-30 03:02:23 -07003183void SingleTouchInputMapper::configureRawAxes() {
3184 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003185
Jeff Brown38a7fab2010-08-30 03:02:23 -07003186 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3187 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3188 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3189 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003190}
3191
3192
3193// --- MultiTouchInputMapper ---
3194
3195MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3196 TouchInputMapper(device, associatedDisplayId) {
3197 initialize();
3198}
3199
3200MultiTouchInputMapper::~MultiTouchInputMapper() {
3201}
3202
3203void MultiTouchInputMapper::initialize() {
3204 mAccumulator.clear();
3205}
3206
3207void MultiTouchInputMapper::reset() {
3208 TouchInputMapper::reset();
3209
Jeff Browne57e8952010-07-23 21:28:06 -07003210 initialize();
3211}
3212
3213void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3214 switch (rawEvent->type) {
3215 case EV_ABS: {
3216 uint32_t pointerIndex = mAccumulator.pointerCount;
3217 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3218
3219 switch (rawEvent->scanCode) {
3220 case ABS_MT_POSITION_X:
3221 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3222 pointer->absMTPositionX = rawEvent->value;
3223 break;
3224 case ABS_MT_POSITION_Y:
3225 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3226 pointer->absMTPositionY = rawEvent->value;
3227 break;
3228 case ABS_MT_TOUCH_MAJOR:
3229 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3230 pointer->absMTTouchMajor = rawEvent->value;
3231 break;
3232 case ABS_MT_TOUCH_MINOR:
3233 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3234 pointer->absMTTouchMinor = rawEvent->value;
3235 break;
3236 case ABS_MT_WIDTH_MAJOR:
3237 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3238 pointer->absMTWidthMajor = rawEvent->value;
3239 break;
3240 case ABS_MT_WIDTH_MINOR:
3241 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3242 pointer->absMTWidthMinor = rawEvent->value;
3243 break;
3244 case ABS_MT_ORIENTATION:
3245 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3246 pointer->absMTOrientation = rawEvent->value;
3247 break;
3248 case ABS_MT_TRACKING_ID:
3249 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3250 pointer->absMTTrackingId = rawEvent->value;
3251 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003252 case ABS_MT_PRESSURE:
3253 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3254 pointer->absMTPressure = rawEvent->value;
3255 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003256 }
3257 break;
3258 }
3259
3260 case EV_SYN:
3261 switch (rawEvent->scanCode) {
3262 case SYN_MT_REPORT: {
3263 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3264 uint32_t pointerIndex = mAccumulator.pointerCount;
3265
3266 if (mAccumulator.pointers[pointerIndex].fields) {
3267 if (pointerIndex == MAX_POINTERS) {
3268 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3269 MAX_POINTERS);
3270 } else {
3271 pointerIndex += 1;
3272 mAccumulator.pointerCount = pointerIndex;
3273 }
3274 }
3275
3276 mAccumulator.pointers[pointerIndex].clear();
3277 break;
3278 }
3279
3280 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003281 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003282 break;
3283 }
3284 break;
3285 }
3286}
3287
3288void MultiTouchInputMapper::sync(nsecs_t when) {
3289 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003290 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003291
Jeff Browne57e8952010-07-23 21:28:06 -07003292 uint32_t inCount = mAccumulator.pointerCount;
3293 uint32_t outCount = 0;
3294 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003295
Jeff Browne57e8952010-07-23 21:28:06 -07003296 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003297
Jeff Browne57e8952010-07-23 21:28:06 -07003298 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003299 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3300 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003301
Jeff Browne57e8952010-07-23 21:28:06 -07003302 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003303 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3304 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003305 continue;
3306 }
3307
Jeff Brownd64c8552010-08-17 20:38:35 -07003308 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3309 outPointer.x = inPointer.absMTPositionX;
3310 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003311
Jeff Brown38a7fab2010-08-30 03:02:23 -07003312 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3313 if (inPointer.absMTPressure <= 0) {
3314 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brownd64c8552010-08-17 20:38:35 -07003315 // a pointer up. Drop this finger.
3316 continue;
3317 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003318 outPointer.pressure = inPointer.absMTPressure;
3319 } else {
3320 // Default pressure to 0 if absent.
3321 outPointer.pressure = 0;
3322 }
3323
3324 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3325 if (inPointer.absMTTouchMajor <= 0) {
3326 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3327 // a pointer going up. Drop this finger.
3328 continue;
3329 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003330 outPointer.touchMajor = inPointer.absMTTouchMajor;
3331 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003332 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003333 outPointer.touchMajor = 0;
3334 }
Jeff Browne839a582010-04-22 18:58:52 -07003335
Jeff Brownd64c8552010-08-17 20:38:35 -07003336 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3337 outPointer.touchMinor = inPointer.absMTTouchMinor;
3338 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003339 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003340 outPointer.touchMinor = outPointer.touchMajor;
3341 }
Jeff Browne839a582010-04-22 18:58:52 -07003342
Jeff Brownd64c8552010-08-17 20:38:35 -07003343 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3344 outPointer.toolMajor = inPointer.absMTWidthMajor;
3345 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003346 // Default tool area to 0 if absent.
3347 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003348 }
Jeff Browne839a582010-04-22 18:58:52 -07003349
Jeff Brownd64c8552010-08-17 20:38:35 -07003350 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3351 outPointer.toolMinor = inPointer.absMTWidthMinor;
3352 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003353 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003354 outPointer.toolMinor = outPointer.toolMajor;
3355 }
3356
3357 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3358 outPointer.orientation = inPointer.absMTOrientation;
3359 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003360 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003361 outPointer.orientation = 0;
3362 }
3363
Jeff Brown38a7fab2010-08-30 03:02:23 -07003364 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003365 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003366 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3367 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003368
Jeff Browne57e8952010-07-23 21:28:06 -07003369 if (id > MAX_POINTER_ID) {
3370#if DEBUG_POINTERS
3371 LOGD("Pointers: Ignoring driver provided pointer id %d because "
3372 "it is larger than max supported id %d for optimizations",
3373 id, MAX_POINTER_ID);
3374#endif
3375 havePointerIds = false;
3376 }
3377 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003378 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003379 mCurrentTouch.idToIndex[id] = outCount;
3380 mCurrentTouch.idBits.markBit(id);
3381 }
3382 } else {
3383 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003384 }
3385 }
Jeff Browne839a582010-04-22 18:58:52 -07003386
Jeff Browne57e8952010-07-23 21:28:06 -07003387 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003388 }
3389
Jeff Browne57e8952010-07-23 21:28:06 -07003390 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003391
Jeff Browne57e8952010-07-23 21:28:06 -07003392 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003393
3394 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003395}
3396
Jeff Brown38a7fab2010-08-30 03:02:23 -07003397void MultiTouchInputMapper::configureRawAxes() {
3398 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003399
Jeff Brown38a7fab2010-08-30 03:02:23 -07003400 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3401 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3402 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3403 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3404 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3405 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3406 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3407 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003408}
3409
Jeff Browne839a582010-04-22 18:58:52 -07003410
3411} // namespace android