blob: f2b029a5e10f43f7e1e63d73bd0ee7d7b63c5660 [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 }
Jeff Browne57e8952010-07-23 21:28:06 -0700328
329 if (keyboardSources != 0) {
330 device->addMapper(new KeyboardInputMapper(device,
331 associatedDisplayId, keyboardSources, keyboardType));
332 }
333
334 // Trackball-like devices.
335 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
336 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
337 }
338
339 // Touchscreen-like devices.
340 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
341 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
342 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
343 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
344 }
345
346 return device;
347}
348
349void InputReader::consumeEvent(const RawEvent* rawEvent) {
350 int32_t deviceId = rawEvent->deviceId;
351
352 { // acquire device registry reader lock
353 RWLock::AutoRLock _rl(mDeviceRegistryLock);
354
355 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
356 if (deviceIndex < 0) {
357 LOGW("Discarding event for unknown deviceId %d.", deviceId);
358 return;
359 }
360
361 InputDevice* device = mDevices.valueAt(deviceIndex);
362 if (device->isIgnored()) {
363 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
364 return;
365 }
366
367 device->process(rawEvent);
368 } // release device registry reader lock
369}
370
371void InputReader::handleConfigurationChanged(nsecs_t when) {
372 // Reset global meta state because it depends on the list of all configured devices.
373 updateGlobalMetaState();
374
375 // Update input configuration.
376 updateInputConfiguration();
377
378 // Enqueue configuration changed.
379 mDispatcher->notifyConfigurationChanged(when);
380}
381
382void InputReader::configureExcludedDevices() {
383 Vector<String8> excludedDeviceNames;
384 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
385
386 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
387 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
388 }
389}
390
391void InputReader::updateGlobalMetaState() {
392 { // acquire state lock
393 AutoMutex _l(mStateLock);
394
395 mGlobalMetaState = 0;
396
397 { // acquire device registry reader lock
398 RWLock::AutoRLock _rl(mDeviceRegistryLock);
399
400 for (size_t i = 0; i < mDevices.size(); i++) {
401 InputDevice* device = mDevices.valueAt(i);
402 mGlobalMetaState |= device->getMetaState();
403 }
404 } // release device registry reader lock
405 } // release state lock
406}
407
408int32_t InputReader::getGlobalMetaState() {
409 { // acquire state lock
410 AutoMutex _l(mStateLock);
411
412 return mGlobalMetaState;
413 } // release state lock
414}
415
416void InputReader::updateInputConfiguration() {
417 { // acquire state lock
418 AutoMutex _l(mStateLock);
419
420 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
421 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
422 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
423 { // acquire device registry reader lock
424 RWLock::AutoRLock _rl(mDeviceRegistryLock);
425
426 InputDeviceInfo deviceInfo;
427 for (size_t i = 0; i < mDevices.size(); i++) {
428 InputDevice* device = mDevices.valueAt(i);
429 device->getDeviceInfo(& deviceInfo);
430 uint32_t sources = deviceInfo.getSources();
431
432 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
433 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
434 }
435 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
436 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
437 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
438 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
439 }
440 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
441 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Browne839a582010-04-22 18:58:52 -0700442 }
443 }
Jeff Browne57e8952010-07-23 21:28:06 -0700444 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700445
Jeff Browne57e8952010-07-23 21:28:06 -0700446 mInputConfiguration.touchScreen = touchScreenConfig;
447 mInputConfiguration.keyboard = keyboardConfig;
448 mInputConfiguration.navigation = navigationConfig;
449 } // release state lock
450}
451
452void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
453 { // acquire state lock
454 AutoMutex _l(mStateLock);
455
456 *outConfiguration = mInputConfiguration;
457 } // release state lock
458}
459
460status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
461 { // acquire device registry reader lock
462 RWLock::AutoRLock _rl(mDeviceRegistryLock);
463
464 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
465 if (deviceIndex < 0) {
466 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700467 }
468
Jeff Browne57e8952010-07-23 21:28:06 -0700469 InputDevice* device = mDevices.valueAt(deviceIndex);
470 if (device->isIgnored()) {
471 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700472 }
Jeff Browne57e8952010-07-23 21:28:06 -0700473
474 device->getDeviceInfo(outDeviceInfo);
475 return OK;
476 } // release device registy reader lock
477}
478
479void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
480 outDeviceIds.clear();
481
482 { // acquire device registry reader lock
483 RWLock::AutoRLock _rl(mDeviceRegistryLock);
484
485 size_t numDevices = mDevices.size();
486 for (size_t i = 0; i < numDevices; i++) {
487 InputDevice* device = mDevices.valueAt(i);
488 if (! device->isIgnored()) {
489 outDeviceIds.add(device->getId());
490 }
491 }
492 } // release device registy reader lock
493}
494
495int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
496 int32_t keyCode) {
497 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
498}
499
500int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
501 int32_t scanCode) {
502 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
503}
504
505int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
506 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
507}
508
509int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
510 GetStateFunc getStateFunc) {
511 { // acquire device registry reader lock
512 RWLock::AutoRLock _rl(mDeviceRegistryLock);
513
514 int32_t result = AKEY_STATE_UNKNOWN;
515 if (deviceId >= 0) {
516 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
517 if (deviceIndex >= 0) {
518 InputDevice* device = mDevices.valueAt(deviceIndex);
519 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
520 result = (device->*getStateFunc)(sourceMask, code);
521 }
522 }
523 } else {
524 size_t numDevices = mDevices.size();
525 for (size_t i = 0; i < numDevices; i++) {
526 InputDevice* device = mDevices.valueAt(i);
527 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
528 result = (device->*getStateFunc)(sourceMask, code);
529 if (result >= AKEY_STATE_DOWN) {
530 return result;
531 }
532 }
533 }
534 }
535 return result;
536 } // release device registy reader lock
537}
538
539bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
540 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
541 memset(outFlags, 0, numCodes);
542 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
543}
544
545bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
546 const int32_t* keyCodes, uint8_t* outFlags) {
547 { // acquire device registry reader lock
548 RWLock::AutoRLock _rl(mDeviceRegistryLock);
549 bool result = false;
550 if (deviceId >= 0) {
551 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
552 if (deviceIndex >= 0) {
553 InputDevice* device = mDevices.valueAt(deviceIndex);
554 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
555 result = device->markSupportedKeyCodes(sourceMask,
556 numCodes, keyCodes, outFlags);
557 }
558 }
559 } else {
560 size_t numDevices = mDevices.size();
561 for (size_t i = 0; i < numDevices; i++) {
562 InputDevice* device = mDevices.valueAt(i);
563 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
564 result |= device->markSupportedKeyCodes(sourceMask,
565 numCodes, keyCodes, outFlags);
566 }
567 }
568 }
569 return result;
570 } // release device registy reader lock
571}
572
Jeff Browna665ca82010-09-08 11:49:43 -0700573void InputReader::dump(String8& dump) {
574 dumpDeviceInfo(dump);
575}
576
577static void dumpMotionRange(String8& dump,
578 const char* name, const InputDeviceInfo::MotionRange* range) {
579 if (range) {
580 dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
581 name, range->min, range->max, range->flat, range->fuzz);
582 }
583}
584
585#define DUMP_MOTION_RANGE(range) \
586 dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
587
588void InputReader::dumpDeviceInfo(String8& dump) {
589 Vector<int32_t> deviceIds;
590 getInputDeviceIds(deviceIds);
591
592 InputDeviceInfo deviceInfo;
593 for (size_t i = 0; i < deviceIds.size(); i++) {
594 int32_t deviceId = deviceIds[i];
595
596 status_t result = getInputDeviceInfo(deviceId, & deviceInfo);
597 if (result == NAME_NOT_FOUND) {
598 continue;
599 } else if (result != OK) {
600 dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
601 result);
602 continue;
603 }
604
605 dump.appendFormat(" Device %d: '%s'\n",
606 deviceInfo.getId(), deviceInfo.getName().string());
607 dump.appendFormat(" sources = 0x%08x\n",
608 deviceInfo.getSources());
609 dump.appendFormat(" keyboardType = %d\n",
610 deviceInfo.getKeyboardType());
611
612 dump.append(" motion ranges:\n");
613 DUMP_MOTION_RANGE(X);
614 DUMP_MOTION_RANGE(Y);
615 DUMP_MOTION_RANGE(PRESSURE);
616 DUMP_MOTION_RANGE(SIZE);
617 DUMP_MOTION_RANGE(TOUCH_MAJOR);
618 DUMP_MOTION_RANGE(TOUCH_MINOR);
619 DUMP_MOTION_RANGE(TOOL_MAJOR);
620 DUMP_MOTION_RANGE(TOOL_MINOR);
621 DUMP_MOTION_RANGE(ORIENTATION);
622 }
623}
624
625#undef DUMP_MOTION_RANGE
626
Jeff Browne57e8952010-07-23 21:28:06 -0700627
628// --- InputReaderThread ---
629
630InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
631 Thread(/*canCallJava*/ true), mReader(reader) {
632}
633
634InputReaderThread::~InputReaderThread() {
635}
636
637bool InputReaderThread::threadLoop() {
638 mReader->loopOnce();
639 return true;
640}
641
642
643// --- InputDevice ---
644
645InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
646 mContext(context), mId(id), mName(name), mSources(0) {
647}
648
649InputDevice::~InputDevice() {
650 size_t numMappers = mMappers.size();
651 for (size_t i = 0; i < numMappers; i++) {
652 delete mMappers[i];
653 }
654 mMappers.clear();
655}
656
657void InputDevice::addMapper(InputMapper* mapper) {
658 mMappers.add(mapper);
659}
660
661void InputDevice::configure() {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700662 if (! isIgnored()) {
663 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
664 }
665
Jeff Browne57e8952010-07-23 21:28:06 -0700666 mSources = 0;
667
668 size_t numMappers = mMappers.size();
669 for (size_t i = 0; i < numMappers; i++) {
670 InputMapper* mapper = mMappers[i];
671 mapper->configure();
672 mSources |= mapper->getSources();
Jeff Browne839a582010-04-22 18:58:52 -0700673 }
674}
675
Jeff Browne57e8952010-07-23 21:28:06 -0700676void InputDevice::reset() {
677 size_t numMappers = mMappers.size();
678 for (size_t i = 0; i < numMappers; i++) {
679 InputMapper* mapper = mMappers[i];
680 mapper->reset();
681 }
682}
Jeff Browne839a582010-04-22 18:58:52 -0700683
Jeff Browne57e8952010-07-23 21:28:06 -0700684void InputDevice::process(const RawEvent* rawEvent) {
685 size_t numMappers = mMappers.size();
686 for (size_t i = 0; i < numMappers; i++) {
687 InputMapper* mapper = mMappers[i];
688 mapper->process(rawEvent);
689 }
690}
Jeff Browne839a582010-04-22 18:58:52 -0700691
Jeff Browne57e8952010-07-23 21:28:06 -0700692void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
693 outDeviceInfo->initialize(mId, mName);
694
695 size_t numMappers = mMappers.size();
696 for (size_t i = 0; i < numMappers; i++) {
697 InputMapper* mapper = mMappers[i];
698 mapper->populateDeviceInfo(outDeviceInfo);
699 }
700}
701
702int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
703 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
704}
705
706int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
707 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
708}
709
710int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
711 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
712}
713
714int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
715 int32_t result = AKEY_STATE_UNKNOWN;
716 size_t numMappers = mMappers.size();
717 for (size_t i = 0; i < numMappers; i++) {
718 InputMapper* mapper = mMappers[i];
719 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
720 result = (mapper->*getStateFunc)(sourceMask, code);
721 if (result >= AKEY_STATE_DOWN) {
722 return result;
723 }
724 }
725 }
726 return result;
727}
728
729bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
730 const int32_t* keyCodes, uint8_t* outFlags) {
731 bool result = false;
732 size_t numMappers = mMappers.size();
733 for (size_t i = 0; i < numMappers; i++) {
734 InputMapper* mapper = mMappers[i];
735 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
736 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
737 }
738 }
739 return result;
740}
741
742int32_t InputDevice::getMetaState() {
743 int32_t result = 0;
744 size_t numMappers = mMappers.size();
745 for (size_t i = 0; i < numMappers; i++) {
746 InputMapper* mapper = mMappers[i];
747 result |= mapper->getMetaState();
748 }
749 return result;
750}
751
752
753// --- InputMapper ---
754
755InputMapper::InputMapper(InputDevice* device) :
756 mDevice(device), mContext(device->getContext()) {
757}
758
759InputMapper::~InputMapper() {
760}
761
762void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
763 info->addSource(getSources());
764}
765
766void InputMapper::configure() {
767}
768
769void InputMapper::reset() {
770}
771
772int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
773 return AKEY_STATE_UNKNOWN;
774}
775
776int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
777 return AKEY_STATE_UNKNOWN;
778}
779
780int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
781 return AKEY_STATE_UNKNOWN;
782}
783
784bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
785 const int32_t* keyCodes, uint8_t* outFlags) {
786 return false;
787}
788
789int32_t InputMapper::getMetaState() {
790 return 0;
791}
792
793bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
Jeff Browne57e8952010-07-23 21:28:06 -0700794 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
795}
796
797
798// --- SwitchInputMapper ---
799
800SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
801 InputMapper(device) {
802}
803
804SwitchInputMapper::~SwitchInputMapper() {
805}
806
807uint32_t SwitchInputMapper::getSources() {
808 return 0;
809}
810
811void SwitchInputMapper::process(const RawEvent* rawEvent) {
812 switch (rawEvent->type) {
813 case EV_SW:
814 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
815 break;
816 }
817}
818
819void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
820 uint32_t policyFlags = 0;
821 int32_t policyActions = getPolicy()->interceptSwitch(
822 when, switchCode, switchValue, policyFlags);
823
824 applyStandardPolicyActions(when, policyActions);
825}
826
827int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
828 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
829}
830
831
832// --- KeyboardInputMapper ---
833
834KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
835 uint32_t sources, int32_t keyboardType) :
836 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
837 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700838 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700839}
840
841KeyboardInputMapper::~KeyboardInputMapper() {
842}
843
Jeff Brownb51719b2010-07-29 18:18:33 -0700844void KeyboardInputMapper::initializeLocked() {
845 mLocked.metaState = AMETA_NONE;
846 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700847}
848
849uint32_t KeyboardInputMapper::getSources() {
850 return mSources;
851}
852
853void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
854 InputMapper::populateDeviceInfo(info);
855
856 info->setKeyboardType(mKeyboardType);
857}
858
859void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700860 for (;;) {
861 int32_t keyCode, scanCode;
862 { // acquire lock
863 AutoMutex _l(mLock);
864
865 // Synthesize key up event on reset if keys are currently down.
866 if (mLocked.keyDowns.isEmpty()) {
867 initializeLocked();
868 break; // done
869 }
870
871 const KeyDown& keyDown = mLocked.keyDowns.top();
872 keyCode = keyDown.keyCode;
873 scanCode = keyDown.scanCode;
874 } // release lock
875
Jeff Browne57e8952010-07-23 21:28:06 -0700876 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700877 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700878 }
879
880 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700881 getContext()->updateGlobalMetaState();
882}
883
884void KeyboardInputMapper::process(const RawEvent* rawEvent) {
885 switch (rawEvent->type) {
886 case EV_KEY: {
887 int32_t scanCode = rawEvent->scanCode;
888 if (isKeyboardOrGamepadKey(scanCode)) {
889 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
890 rawEvent->flags);
891 }
892 break;
893 }
894 }
895}
896
897bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
898 return scanCode < BTN_MOUSE
899 || scanCode >= KEY_OK
900 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
901}
902
Jeff Brownb51719b2010-07-29 18:18:33 -0700903void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
904 int32_t scanCode, uint32_t policyFlags) {
905 int32_t newMetaState;
906 nsecs_t downTime;
907 bool metaStateChanged = false;
908
909 { // acquire lock
910 AutoMutex _l(mLock);
911
912 if (down) {
913 // Rotate key codes according to orientation if needed.
914 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
915 if (mAssociatedDisplayId >= 0) {
916 int32_t orientation;
917 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
918 return;
919 }
920
921 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700922 }
923
Jeff Brownb51719b2010-07-29 18:18:33 -0700924 // Add key down.
925 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
926 if (keyDownIndex >= 0) {
927 // key repeat, be sure to use same keycode as before in case of rotation
928 keyCode = mLocked.keyDowns.top().keyCode;
929 } else {
930 // key down
931 mLocked.keyDowns.push();
932 KeyDown& keyDown = mLocked.keyDowns.editTop();
933 keyDown.keyCode = keyCode;
934 keyDown.scanCode = scanCode;
935 }
936
937 mLocked.downTime = when;
938 } else {
939 // Remove key down.
940 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
941 if (keyDownIndex >= 0) {
942 // key up, be sure to use same keycode as before in case of rotation
943 keyCode = mLocked.keyDowns.top().keyCode;
944 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
945 } else {
946 // key was not actually down
947 LOGI("Dropping key up from device %s because the key was not down. "
948 "keyCode=%d, scanCode=%d",
949 getDeviceName().string(), keyCode, scanCode);
950 return;
951 }
Jeff Browne57e8952010-07-23 21:28:06 -0700952 }
953
Jeff Brownb51719b2010-07-29 18:18:33 -0700954 int32_t oldMetaState = mLocked.metaState;
955 newMetaState = updateMetaState(keyCode, down, oldMetaState);
956 if (oldMetaState != newMetaState) {
957 mLocked.metaState = newMetaState;
958 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700959 }
Jeff Brown8575a872010-06-30 16:10:35 -0700960
Jeff Brownb51719b2010-07-29 18:18:33 -0700961 downTime = mLocked.downTime;
962 } // release lock
963
964 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700965 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700966 }
967
Jeff Brownb51719b2010-07-29 18:18:33 -0700968 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
969}
Jeff Browne839a582010-04-22 18:58:52 -0700970
Jeff Brownb51719b2010-07-29 18:18:33 -0700971void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
972 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -0700973 int32_t policyActions = getPolicy()->interceptKey(when,
974 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700975
Jeff Browne57e8952010-07-23 21:28:06 -0700976 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Browne839a582010-04-22 18:58:52 -0700977 return; // event dropped
978 }
979
Jeff Brownb51719b2010-07-29 18:18:33 -0700980 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700981 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Browne57e8952010-07-23 21:28:06 -0700982 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700983 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Browne839a582010-04-22 18:58:52 -0700984 }
985
Jeff Browne57e8952010-07-23 21:28:06 -0700986 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brownb51719b2010-07-29 18:18:33 -0700987 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700988}
989
Jeff Brownb51719b2010-07-29 18:18:33 -0700990ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
991 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -0700992 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700993 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -0700994 return i;
995 }
996 }
997 return -1;
Jeff Browne839a582010-04-22 18:58:52 -0700998}
999
Jeff Browne57e8952010-07-23 21:28:06 -07001000int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1001 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1002}
Jeff Browne839a582010-04-22 18:58:52 -07001003
Jeff Browne57e8952010-07-23 21:28:06 -07001004int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1005 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1006}
Jeff Browne839a582010-04-22 18:58:52 -07001007
Jeff Browne57e8952010-07-23 21:28:06 -07001008bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1009 const int32_t* keyCodes, uint8_t* outFlags) {
1010 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1011}
1012
1013int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001014 { // acquire lock
1015 AutoMutex _l(mLock);
1016 return mLocked.metaState;
1017 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001018}
1019
1020
1021// --- TrackballInputMapper ---
1022
1023TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1024 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1025 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1026 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1027 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1028 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1029
Jeff Brownb51719b2010-07-29 18:18:33 -07001030 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001031}
1032
1033TrackballInputMapper::~TrackballInputMapper() {
1034}
1035
1036uint32_t TrackballInputMapper::getSources() {
1037 return AINPUT_SOURCE_TRACKBALL;
1038}
1039
1040void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1041 InputMapper::populateDeviceInfo(info);
1042
1043 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1044 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1045}
1046
Jeff Brownb51719b2010-07-29 18:18:33 -07001047void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001048 mAccumulator.clear();
1049
Jeff Brownb51719b2010-07-29 18:18:33 -07001050 mLocked.down = false;
1051 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001052}
1053
1054void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001055 for (;;) {
1056 { // acquire lock
1057 AutoMutex _l(mLock);
1058
1059 if (! mLocked.down) {
1060 initializeLocked();
1061 break; // done
1062 }
1063 } // release lock
1064
1065 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001066 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001067 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001068 mAccumulator.btnMouse = false;
1069 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001070 }
1071
Jeff Browne57e8952010-07-23 21:28:06 -07001072 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001073}
Jeff Browne839a582010-04-22 18:58:52 -07001074
Jeff Browne57e8952010-07-23 21:28:06 -07001075void TrackballInputMapper::process(const RawEvent* rawEvent) {
1076 switch (rawEvent->type) {
1077 case EV_KEY:
1078 switch (rawEvent->scanCode) {
1079 case BTN_MOUSE:
1080 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1081 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001082 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1083 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001084 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001085 break;
Jeff Browne839a582010-04-22 18:58:52 -07001086 }
Jeff Browne57e8952010-07-23 21:28:06 -07001087 break;
Jeff Browne839a582010-04-22 18:58:52 -07001088
Jeff Browne57e8952010-07-23 21:28:06 -07001089 case EV_REL:
1090 switch (rawEvent->scanCode) {
1091 case REL_X:
1092 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1093 mAccumulator.relX = rawEvent->value;
1094 break;
1095 case REL_Y:
1096 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1097 mAccumulator.relY = rawEvent->value;
1098 break;
Jeff Browne839a582010-04-22 18:58:52 -07001099 }
Jeff Browne57e8952010-07-23 21:28:06 -07001100 break;
Jeff Browne839a582010-04-22 18:58:52 -07001101
Jeff Browne57e8952010-07-23 21:28:06 -07001102 case EV_SYN:
1103 switch (rawEvent->scanCode) {
1104 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001105 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001106 break;
Jeff Browne839a582010-04-22 18:58:52 -07001107 }
Jeff Browne57e8952010-07-23 21:28:06 -07001108 break;
Jeff Browne839a582010-04-22 18:58:52 -07001109 }
Jeff Browne839a582010-04-22 18:58:52 -07001110}
1111
Jeff Browne57e8952010-07-23 21:28:06 -07001112void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001113 uint32_t fields = mAccumulator.fields;
1114 if (fields == 0) {
1115 return; // no new state changes, so nothing to do
1116 }
1117
Jeff Brownb51719b2010-07-29 18:18:33 -07001118 int motionEventAction;
1119 PointerCoords pointerCoords;
1120 nsecs_t downTime;
1121 { // acquire lock
1122 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001123
Jeff Brownb51719b2010-07-29 18:18:33 -07001124 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1125
1126 if (downChanged) {
1127 if (mAccumulator.btnMouse) {
1128 mLocked.down = true;
1129 mLocked.downTime = when;
1130 } else {
1131 mLocked.down = false;
1132 }
Jeff Browne57e8952010-07-23 21:28:06 -07001133 }
Jeff Browne839a582010-04-22 18:58:52 -07001134
Jeff Brownb51719b2010-07-29 18:18:33 -07001135 downTime = mLocked.downTime;
1136 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1137 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001138
Jeff Brownb51719b2010-07-29 18:18:33 -07001139 if (downChanged) {
1140 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001141 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001142 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001143 }
Jeff Browne839a582010-04-22 18:58:52 -07001144
Jeff Brownb51719b2010-07-29 18:18:33 -07001145 pointerCoords.x = x;
1146 pointerCoords.y = y;
1147 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1148 pointerCoords.size = 0;
1149 pointerCoords.touchMajor = 0;
1150 pointerCoords.touchMinor = 0;
1151 pointerCoords.toolMajor = 0;
1152 pointerCoords.toolMinor = 0;
1153 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001154
Jeff Brownb51719b2010-07-29 18:18:33 -07001155 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1156 // Rotate motion based on display orientation if needed.
1157 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1158 int32_t orientation;
1159 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1160 return;
1161 }
1162
1163 float temp;
1164 switch (orientation) {
1165 case InputReaderPolicyInterface::ROTATION_90:
1166 temp = pointerCoords.x;
1167 pointerCoords.x = pointerCoords.y;
1168 pointerCoords.y = - temp;
1169 break;
1170
1171 case InputReaderPolicyInterface::ROTATION_180:
1172 pointerCoords.x = - pointerCoords.x;
1173 pointerCoords.y = - pointerCoords.y;
1174 break;
1175
1176 case InputReaderPolicyInterface::ROTATION_270:
1177 temp = pointerCoords.x;
1178 pointerCoords.x = - pointerCoords.y;
1179 pointerCoords.y = temp;
1180 break;
1181 }
1182 }
1183 } // release lock
1184
1185 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
Jeff Brownd64c8552010-08-17 20:38:35 -07001186
1187 mAccumulator.clear();
Jeff Brownb51719b2010-07-29 18:18:33 -07001188}
1189
1190void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1191 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001192 uint32_t policyFlags = 0;
1193 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1194
1195 if (! applyStandardPolicyActions(when, policyActions)) {
1196 return; // event dropped
1197 }
1198
Jeff Browne57e8952010-07-23 21:28:06 -07001199 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001200 int32_t pointerId = 0;
1201
Jeff Browne57e8952010-07-23 21:28:06 -07001202 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001203 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001204 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001205}
1206
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001207int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1208 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1209 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1210 } else {
1211 return AKEY_STATE_UNKNOWN;
1212 }
1213}
1214
Jeff Browne57e8952010-07-23 21:28:06 -07001215
1216// --- TouchInputMapper ---
1217
1218TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001219 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1220 mLocked.surfaceOrientation = -1;
1221 mLocked.surfaceWidth = -1;
1222 mLocked.surfaceHeight = -1;
1223
1224 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001225}
1226
1227TouchInputMapper::~TouchInputMapper() {
1228}
1229
1230uint32_t TouchInputMapper::getSources() {
1231 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1232}
1233
1234void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1235 InputMapper::populateDeviceInfo(info);
1236
Jeff Brownb51719b2010-07-29 18:18:33 -07001237 { // acquire lock
1238 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001239
Jeff Brownb51719b2010-07-29 18:18:33 -07001240 // Ensure surface information is up to date so that orientation changes are
1241 // noticed immediately.
1242 configureSurfaceLocked();
1243
1244 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1245 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001246
1247 if (mLocked.orientedRanges.havePressure) {
1248 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1249 mLocked.orientedRanges.pressure);
1250 }
1251
1252 if (mLocked.orientedRanges.haveSize) {
1253 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1254 mLocked.orientedRanges.size);
1255 }
1256
1257 if (mLocked.orientedRanges.haveTouchArea) {
1258 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1259 mLocked.orientedRanges.touchMajor);
1260 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1261 mLocked.orientedRanges.touchMinor);
1262 }
1263
1264 if (mLocked.orientedRanges.haveToolArea) {
1265 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1266 mLocked.orientedRanges.toolMajor);
1267 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1268 mLocked.orientedRanges.toolMinor);
1269 }
1270
1271 if (mLocked.orientedRanges.haveOrientation) {
1272 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1273 mLocked.orientedRanges.orientation);
1274 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001275 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001276}
1277
Jeff Brownb51719b2010-07-29 18:18:33 -07001278void TouchInputMapper::initializeLocked() {
1279 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001280 mLastTouch.clear();
1281 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001282
1283 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1284 mAveragingTouchFilter.historyStart[i] = 0;
1285 mAveragingTouchFilter.historyEnd[i] = 0;
1286 }
1287
1288 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001289
1290 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001291
1292 mLocked.orientedRanges.havePressure = false;
1293 mLocked.orientedRanges.haveSize = false;
1294 mLocked.orientedRanges.haveTouchArea = false;
1295 mLocked.orientedRanges.haveToolArea = false;
1296 mLocked.orientedRanges.haveOrientation = false;
1297}
1298
Jeff Browne57e8952010-07-23 21:28:06 -07001299void TouchInputMapper::configure() {
1300 InputMapper::configure();
1301
1302 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001303 configureParameters();
Jeff Browna665ca82010-09-08 11:49:43 -07001304 logParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001305
1306 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001307 configureRawAxes();
1308 logRawAxes();
1309
1310 // Prepare input device calibration.
1311 parseCalibration();
1312 resolveCalibration();
1313 logCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001314
Jeff Brownb51719b2010-07-29 18:18:33 -07001315 { // acquire lock
1316 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001317
Jeff Brown38a7fab2010-08-30 03:02:23 -07001318 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001319 configureSurfaceLocked();
1320 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001321}
1322
Jeff Brown38a7fab2010-08-30 03:02:23 -07001323void TouchInputMapper::configureParameters() {
1324 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1325 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1326 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1327}
1328
Jeff Browna665ca82010-09-08 11:49:43 -07001329void TouchInputMapper::logParameters() {
1330 if (mParameters.useBadTouchFilter) {
1331 LOGI(INDENT "Bad touch filter enabled.");
1332 }
1333 if (mParameters.useAveragingTouchFilter) {
1334 LOGI(INDENT "Averaging touch filter enabled.");
1335 }
1336 if (mParameters.useJumpyTouchFilter) {
1337 LOGI(INDENT "Jumpy touch filter enabled.");
1338 }
1339}
1340
Jeff Brown38a7fab2010-08-30 03:02:23 -07001341void TouchInputMapper::configureRawAxes() {
1342 mRawAxes.x.clear();
1343 mRawAxes.y.clear();
1344 mRawAxes.pressure.clear();
1345 mRawAxes.touchMajor.clear();
1346 mRawAxes.touchMinor.clear();
1347 mRawAxes.toolMajor.clear();
1348 mRawAxes.toolMinor.clear();
1349 mRawAxes.orientation.clear();
1350}
1351
Jeff Browna665ca82010-09-08 11:49:43 -07001352static void logAxisInfo(RawAbsoluteAxisInfo axis, const char* name) {
1353 if (axis.valid) {
1354 LOGI(INDENT "Raw %s axis: min=%d, max=%d, flat=%d, fuzz=%d",
1355 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1356 } else {
1357 LOGI(INDENT "Raw %s axis: unknown range", name);
1358 }
1359}
1360
Jeff Brown38a7fab2010-08-30 03:02:23 -07001361void TouchInputMapper::logRawAxes() {
1362 logAxisInfo(mRawAxes.x, "x");
1363 logAxisInfo(mRawAxes.y, "y");
1364 logAxisInfo(mRawAxes.pressure, "pressure");
1365 logAxisInfo(mRawAxes.touchMajor, "touchMajor");
1366 logAxisInfo(mRawAxes.touchMinor, "touchMinor");
1367 logAxisInfo(mRawAxes.toolMajor, "toolMajor");
1368 logAxisInfo(mRawAxes.toolMinor, "toolMinor");
1369 logAxisInfo(mRawAxes.orientation, "orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001370}
1371
Jeff Brownb51719b2010-07-29 18:18:33 -07001372bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001373 // Update orientation and dimensions if needed.
1374 int32_t orientation;
1375 int32_t width, height;
1376 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001377 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001378 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1379 return false;
1380 }
1381 } else {
1382 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001383 width = mRawAxes.x.getRange();
1384 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001385 }
1386
Jeff Brownb51719b2010-07-29 18:18:33 -07001387 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001388 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001389 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001390 }
1391
Jeff Brownb51719b2010-07-29 18:18:33 -07001392 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001393 if (sizeChanged) {
Jeff Browna665ca82010-09-08 11:49:43 -07001394 LOGI("Device reconfigured (display size changed): id=0x%x, name=%s",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001395 getDeviceId(), getDeviceName().string());
Jeff Browna665ca82010-09-08 11:49:43 -07001396 LOGI(INDENT "Width: %dpx", width);
1397 LOGI(INDENT "Height: %dpx", height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001398
Jeff Brownb51719b2010-07-29 18:18:33 -07001399 mLocked.surfaceWidth = width;
1400 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001401
Jeff Brown38a7fab2010-08-30 03:02:23 -07001402 // Configure X and Y factors.
1403 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1404 mLocked.xOrigin = mRawAxes.x.minValue;
1405 mLocked.yOrigin = mRawAxes.y.minValue;
1406 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1407 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001408 mLocked.xPrecision = 1.0f / mLocked.xScale;
1409 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001410
Jeff Brownb51719b2010-07-29 18:18:33 -07001411 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001412 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001413 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001414 mLocked.xOrigin = 0;
1415 mLocked.yOrigin = 0;
1416 mLocked.xScale = 1.0f;
1417 mLocked.yScale = 1.0f;
1418 mLocked.xPrecision = 1.0f;
1419 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001420 }
1421
Jeff Brown38a7fab2010-08-30 03:02:23 -07001422 // Scale factor for terms that are not oriented in a particular axis.
1423 // If the pixels are square then xScale == yScale otherwise we fake it
1424 // by choosing an average.
1425 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001426
Jeff Brown38a7fab2010-08-30 03:02:23 -07001427 // Size of diagonal axis.
1428 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001429
Jeff Brown38a7fab2010-08-30 03:02:23 -07001430 // TouchMajor and TouchMinor factors.
1431 if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) {
1432 mLocked.orientedRanges.haveTouchArea = true;
1433 mLocked.orientedRanges.touchMajor.min = 0;
1434 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1435 mLocked.orientedRanges.touchMajor.flat = 0;
1436 mLocked.orientedRanges.touchMajor.fuzz = 0;
1437 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1438 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001439
Jeff Brown38a7fab2010-08-30 03:02:23 -07001440 // ToolMajor and ToolMinor factors.
1441 if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1442 mLocked.toolAreaLinearScale = 0;
1443 mLocked.toolAreaLinearBias = 0;
1444 if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) {
1445 if (mCalibration.haveToolAreaLinearScale) {
1446 mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale;
1447 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1448 mLocked.toolAreaLinearScale = float(min(width, height))
1449 / mRawAxes.toolMajor.maxValue;
1450 }
1451
1452 if (mCalibration.haveToolAreaLinearBias) {
1453 mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias;
1454 }
1455 }
1456
1457 mLocked.orientedRanges.haveToolArea = true;
1458 mLocked.orientedRanges.toolMajor.min = 0;
1459 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1460 mLocked.orientedRanges.toolMajor.flat = 0;
1461 mLocked.orientedRanges.toolMajor.fuzz = 0;
1462 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1463 }
1464
1465 // Pressure factors.
1466 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1467 RawAbsoluteAxisInfo rawPressureAxis;
1468 switch (mCalibration.pressureSource) {
1469 case Calibration::PRESSURE_SOURCE_PRESSURE:
1470 rawPressureAxis = mRawAxes.pressure;
1471 break;
1472 case Calibration::PRESSURE_SOURCE_TOUCH:
1473 rawPressureAxis = mRawAxes.touchMajor;
1474 break;
1475 default:
1476 rawPressureAxis.clear();
1477 }
1478
1479 mLocked.pressureScale = 0;
1480 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1481 || mCalibration.pressureCalibration
1482 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1483 if (mCalibration.havePressureScale) {
1484 mLocked.pressureScale = mCalibration.pressureScale;
1485 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1486 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1487 }
1488 }
1489
1490 mLocked.orientedRanges.havePressure = true;
1491 mLocked.orientedRanges.pressure.min = 0;
1492 mLocked.orientedRanges.pressure.max = 1.0;
1493 mLocked.orientedRanges.pressure.flat = 0;
1494 mLocked.orientedRanges.pressure.fuzz = 0;
1495 }
1496
1497 // Size factors.
1498 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1499 mLocked.sizeScale = 0;
1500 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1501 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1502 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1503 }
1504 }
1505
1506 mLocked.orientedRanges.haveSize = true;
1507 mLocked.orientedRanges.size.min = 0;
1508 mLocked.orientedRanges.size.max = 1.0;
1509 mLocked.orientedRanges.size.flat = 0;
1510 mLocked.orientedRanges.size.fuzz = 0;
1511 }
1512
1513 // Orientation
1514 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1515 mLocked.orientationScale = 0;
1516 if (mCalibration.orientationCalibration
1517 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1518 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1519 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1520 }
1521 }
1522
1523 mLocked.orientedRanges.orientation.min = - M_PI_2;
1524 mLocked.orientedRanges.orientation.max = M_PI_2;
1525 mLocked.orientedRanges.orientation.flat = 0;
1526 mLocked.orientedRanges.orientation.fuzz = 0;
1527 }
Jeff Browne57e8952010-07-23 21:28:06 -07001528 }
1529
1530 if (orientationChanged || sizeChanged) {
1531 // Compute oriented surface dimensions, precision, and scales.
1532 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001533 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001534 case InputReaderPolicyInterface::ROTATION_90:
1535 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001536 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1537 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1538 mLocked.orientedXPrecision = mLocked.yPrecision;
1539 mLocked.orientedYPrecision = mLocked.xPrecision;
1540 orientedXScale = mLocked.yScale;
1541 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001542 break;
1543 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001544 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1545 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1546 mLocked.orientedXPrecision = mLocked.xPrecision;
1547 mLocked.orientedYPrecision = mLocked.yPrecision;
1548 orientedXScale = mLocked.xScale;
1549 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001550 break;
1551 }
1552
1553 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001554 mLocked.orientedRanges.x.min = 0;
1555 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1556 mLocked.orientedRanges.x.flat = 0;
1557 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001558
Jeff Brownb51719b2010-07-29 18:18:33 -07001559 mLocked.orientedRanges.y.min = 0;
1560 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1561 mLocked.orientedRanges.y.flat = 0;
1562 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001563 }
1564
Jeff Browna665ca82010-09-08 11:49:43 -07001565 if (sizeChanged) {
1566 logMotionRangesLocked();
1567 }
1568
Jeff Browne57e8952010-07-23 21:28:06 -07001569 return true;
1570}
1571
Jeff Browna665ca82010-09-08 11:49:43 -07001572static void logMotionRangeInfo(InputDeviceInfo::MotionRange* range, const char* name) {
1573 if (range) {
1574 LOGI(INDENT "Output %s range: min=%f, max=%f, flat=%f, fuzz=%f",
1575 name, range->min, range->max, range->flat, range->fuzz);
1576 } else {
1577 LOGI(INDENT "Output %s range: unsupported", name);
1578 }
1579}
1580
1581void TouchInputMapper::logMotionRangesLocked() {
1582 logMotionRangeInfo(& mLocked.orientedRanges.x, "x");
1583 logMotionRangeInfo(& mLocked.orientedRanges.y, "y");
1584 logMotionRangeInfo(mLocked.orientedRanges.havePressure
1585 ? & mLocked.orientedRanges.pressure : NULL, "pressure");
1586 logMotionRangeInfo(mLocked.orientedRanges.haveSize
1587 ? & mLocked.orientedRanges.size : NULL, "size");
1588 logMotionRangeInfo(mLocked.orientedRanges.haveTouchArea
1589 ? & mLocked.orientedRanges.touchMajor : NULL, "touchMajor");
1590 logMotionRangeInfo(mLocked.orientedRanges.haveTouchArea
1591 ? & mLocked.orientedRanges.touchMinor : NULL, "touchMinor");
1592 logMotionRangeInfo(mLocked.orientedRanges.haveToolArea
1593 ? & mLocked.orientedRanges.toolMajor : NULL, "toolMajor");
1594 logMotionRangeInfo(mLocked.orientedRanges.haveToolArea
1595 ? & mLocked.orientedRanges.toolMinor : NULL, "toolMinor");
1596 logMotionRangeInfo(mLocked.orientedRanges.haveOrientation
1597 ? & mLocked.orientedRanges.orientation : NULL, "orientation");
1598}
1599
Jeff Brownb51719b2010-07-29 18:18:33 -07001600void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001601 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001602
Jeff Brownb51719b2010-07-29 18:18:33 -07001603 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001604 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001605 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1606
Jeff Brownb51719b2010-07-29 18:18:33 -07001607 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001608
Jeff Brownb51719b2010-07-29 18:18:33 -07001609 if (virtualKeyDefinitions.size() == 0) {
1610 return;
1611 }
Jeff Browne57e8952010-07-23 21:28:06 -07001612
Jeff Brownb51719b2010-07-29 18:18:33 -07001613 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1614
Jeff Brown38a7fab2010-08-30 03:02:23 -07001615 int32_t touchScreenLeft = mRawAxes.x.minValue;
1616 int32_t touchScreenTop = mRawAxes.y.minValue;
1617 int32_t touchScreenWidth = mRawAxes.x.getRange();
1618 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001619
1620 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001621 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001622 virtualKeyDefinitions[i];
1623
1624 mLocked.virtualKeys.add();
1625 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1626
1627 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1628 int32_t keyCode;
1629 uint32_t flags;
1630 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1631 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001632 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1633 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001634 mLocked.virtualKeys.pop(); // drop the key
1635 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001636 }
1637
Jeff Brownb51719b2010-07-29 18:18:33 -07001638 virtualKey.keyCode = keyCode;
1639 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001640
Jeff Brownb51719b2010-07-29 18:18:33 -07001641 // convert the key definition's display coordinates into touch coordinates for a hit box
1642 int32_t halfWidth = virtualKeyDefinition.width / 2;
1643 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001644
Jeff Brownb51719b2010-07-29 18:18:33 -07001645 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1646 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1647 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1648 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1649 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1650 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1651 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1652 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001653
Jeff Brown38a7fab2010-08-30 03:02:23 -07001654 LOGI(INDENT "VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
Jeff Brownb51719b2010-07-29 18:18:33 -07001655 virtualKey.scanCode, virtualKey.keyCode,
1656 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1657 }
Jeff Browne57e8952010-07-23 21:28:06 -07001658}
1659
Jeff Brown38a7fab2010-08-30 03:02:23 -07001660void TouchInputMapper::parseCalibration() {
1661 const InputDeviceCalibration& in = getDevice()->getCalibration();
1662 Calibration& out = mCalibration;
1663
1664 // Touch Area
1665 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT;
1666 String8 touchAreaCalibrationString;
1667 if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) {
1668 if (touchAreaCalibrationString == "none") {
1669 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1670 } else if (touchAreaCalibrationString == "geometric") {
1671 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC;
1672 } else if (touchAreaCalibrationString == "pressure") {
1673 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1674 } else if (touchAreaCalibrationString != "default") {
1675 LOGW("Invalid value for touch.touchArea.calibration: '%s'",
1676 touchAreaCalibrationString.string());
1677 }
1678 }
1679
1680 // Tool Area
1681 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT;
1682 String8 toolAreaCalibrationString;
1683 if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) {
1684 if (toolAreaCalibrationString == "none") {
1685 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1686 } else if (toolAreaCalibrationString == "geometric") {
1687 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC;
1688 } else if (toolAreaCalibrationString == "linear") {
1689 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1690 } else if (toolAreaCalibrationString != "default") {
1691 LOGW("Invalid value for tool.toolArea.calibration: '%s'",
1692 toolAreaCalibrationString.string());
1693 }
1694 }
1695
1696 out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"),
1697 out.toolAreaLinearScale);
1698 out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"),
1699 out.toolAreaLinearBias);
1700 out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"),
1701 out.toolAreaIsSummed);
1702
1703 // Pressure
1704 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1705 String8 pressureCalibrationString;
1706 if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) {
1707 if (pressureCalibrationString == "none") {
1708 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1709 } else if (pressureCalibrationString == "physical") {
1710 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1711 } else if (pressureCalibrationString == "amplitude") {
1712 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1713 } else if (pressureCalibrationString != "default") {
1714 LOGW("Invalid value for tool.pressure.calibration: '%s'",
1715 pressureCalibrationString.string());
1716 }
1717 }
1718
1719 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1720 String8 pressureSourceString;
1721 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1722 if (pressureSourceString == "pressure") {
1723 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1724 } else if (pressureSourceString == "touch") {
1725 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1726 } else if (pressureSourceString != "default") {
1727 LOGW("Invalid value for touch.pressure.source: '%s'",
1728 pressureSourceString.string());
1729 }
1730 }
1731
1732 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1733 out.pressureScale);
1734
1735 // Size
1736 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1737 String8 sizeCalibrationString;
1738 if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) {
1739 if (sizeCalibrationString == "none") {
1740 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1741 } else if (sizeCalibrationString == "normalized") {
1742 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1743 } else if (sizeCalibrationString != "default") {
1744 LOGW("Invalid value for tool.size.calibration: '%s'",
1745 sizeCalibrationString.string());
1746 }
1747 }
1748
1749 // Orientation
1750 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1751 String8 orientationCalibrationString;
1752 if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) {
1753 if (orientationCalibrationString == "none") {
1754 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1755 } else if (orientationCalibrationString == "interpolated") {
1756 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1757 } else if (orientationCalibrationString != "default") {
1758 LOGW("Invalid value for tool.orientation.calibration: '%s'",
1759 orientationCalibrationString.string());
1760 }
1761 }
1762}
1763
1764void TouchInputMapper::resolveCalibration() {
1765 // Pressure
1766 switch (mCalibration.pressureSource) {
1767 case Calibration::PRESSURE_SOURCE_DEFAULT:
1768 if (mRawAxes.pressure.valid) {
1769 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1770 } else if (mRawAxes.touchMajor.valid) {
1771 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1772 }
1773 break;
1774
1775 case Calibration::PRESSURE_SOURCE_PRESSURE:
1776 if (! mRawAxes.pressure.valid) {
1777 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1778 "the pressure axis is not available.");
1779 }
1780 break;
1781
1782 case Calibration::PRESSURE_SOURCE_TOUCH:
1783 if (! mRawAxes.touchMajor.valid) {
1784 LOGW("Calibration property touch.pressure.source is 'touch' but "
1785 "the touchMajor axis is not available.");
1786 }
1787 break;
1788
1789 default:
1790 break;
1791 }
1792
1793 switch (mCalibration.pressureCalibration) {
1794 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1795 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1796 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1797 } else {
1798 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1799 }
1800 break;
1801
1802 default:
1803 break;
1804 }
1805
1806 // Tool Area
1807 switch (mCalibration.toolAreaCalibration) {
1808 case Calibration::TOOL_AREA_CALIBRATION_DEFAULT:
1809 if (mRawAxes.toolMajor.valid) {
1810 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1811 } else {
1812 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1813 }
1814 break;
1815
1816 default:
1817 break;
1818 }
1819
1820 // Touch Area
1821 switch (mCalibration.touchAreaCalibration) {
1822 case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT:
1823 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
1824 && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1825 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1826 } else {
1827 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1828 }
1829 break;
1830
1831 default:
1832 break;
1833 }
1834
1835 // Size
1836 switch (mCalibration.sizeCalibration) {
1837 case Calibration::SIZE_CALIBRATION_DEFAULT:
1838 if (mRawAxes.toolMajor.valid) {
1839 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1840 } else {
1841 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1842 }
1843 break;
1844
1845 default:
1846 break;
1847 }
1848
1849 // Orientation
1850 switch (mCalibration.orientationCalibration) {
1851 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1852 if (mRawAxes.orientation.valid) {
1853 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1854 } else {
1855 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1856 }
1857 break;
1858
1859 default:
1860 break;
1861 }
1862}
1863
1864void TouchInputMapper::logCalibration() {
Jeff Browna665ca82010-09-08 11:49:43 -07001865 LOGI(INDENT "Calibration:");
1866
Jeff Brown38a7fab2010-08-30 03:02:23 -07001867 // Touch Area
1868 switch (mCalibration.touchAreaCalibration) {
1869 case Calibration::TOUCH_AREA_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001870 LOGI(INDENT INDENT "touch.touchArea.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001871 break;
1872 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
Jeff Browna665ca82010-09-08 11:49:43 -07001873 LOGI(INDENT INDENT "touch.touchArea.calibration: geometric");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001874 break;
1875 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
Jeff Browna665ca82010-09-08 11:49:43 -07001876 LOGI(INDENT INDENT "touch.touchArea.calibration: pressure");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001877 break;
1878 default:
1879 assert(false);
1880 }
1881
1882 // Tool Area
1883 switch (mCalibration.toolAreaCalibration) {
1884 case Calibration::TOOL_AREA_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001885 LOGI(INDENT INDENT "touch.toolArea.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001886 break;
1887 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
Jeff Browna665ca82010-09-08 11:49:43 -07001888 LOGI(INDENT INDENT "touch.toolArea.calibration: geometric");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001889 break;
1890 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
Jeff Browna665ca82010-09-08 11:49:43 -07001891 LOGI(INDENT INDENT "touch.toolArea.calibration: linear");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001892 break;
1893 default:
1894 assert(false);
1895 }
1896
1897 if (mCalibration.haveToolAreaLinearScale) {
Jeff Browna665ca82010-09-08 11:49:43 -07001898 LOGI(INDENT INDENT "touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001899 }
1900
1901 if (mCalibration.haveToolAreaLinearBias) {
Jeff Browna665ca82010-09-08 11:49:43 -07001902 LOGI(INDENT INDENT "touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001903 }
1904
1905 if (mCalibration.haveToolAreaIsSummed) {
Jeff Browna665ca82010-09-08 11:49:43 -07001906 LOGI(INDENT INDENT "touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001907 }
1908
1909 // Pressure
1910 switch (mCalibration.pressureCalibration) {
1911 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001912 LOGI(INDENT INDENT "touch.pressure.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001913 break;
1914 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Browna665ca82010-09-08 11:49:43 -07001915 LOGI(INDENT INDENT "touch.pressure.calibration: physical");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001916 break;
1917 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Browna665ca82010-09-08 11:49:43 -07001918 LOGI(INDENT INDENT "touch.pressure.calibration: amplitude");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001919 break;
1920 default:
1921 assert(false);
1922 }
1923
1924 switch (mCalibration.pressureSource) {
1925 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Browna665ca82010-09-08 11:49:43 -07001926 LOGI(INDENT INDENT "touch.pressure.source: pressure");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001927 break;
1928 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Browna665ca82010-09-08 11:49:43 -07001929 LOGI(INDENT INDENT "touch.pressure.source: touch");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001930 break;
1931 case Calibration::PRESSURE_SOURCE_DEFAULT:
1932 break;
1933 default:
1934 assert(false);
1935 }
1936
1937 if (mCalibration.havePressureScale) {
Jeff Browna665ca82010-09-08 11:49:43 -07001938 LOGI(INDENT INDENT "touch.pressure.scale: %f", mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001939 }
1940
1941 // Size
1942 switch (mCalibration.sizeCalibration) {
1943 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001944 LOGI(INDENT INDENT "touch.size.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001945 break;
1946 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Browna665ca82010-09-08 11:49:43 -07001947 LOGI(INDENT INDENT "touch.size.calibration: normalized");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001948 break;
1949 default:
1950 assert(false);
1951 }
1952
1953 // Orientation
1954 switch (mCalibration.orientationCalibration) {
1955 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Browna665ca82010-09-08 11:49:43 -07001956 LOGI(INDENT INDENT "touch.orientation.calibration: none");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001957 break;
1958 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Browna665ca82010-09-08 11:49:43 -07001959 LOGI(INDENT INDENT "touch.orientation.calibration: interpolated");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001960 break;
1961 default:
1962 assert(false);
1963 }
1964}
1965
Jeff Browne57e8952010-07-23 21:28:06 -07001966void TouchInputMapper::reset() {
1967 // Synthesize touch up event if touch is currently down.
1968 // This will also take care of finishing virtual key processing if needed.
1969 if (mLastTouch.pointerCount != 0) {
1970 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1971 mCurrentTouch.clear();
1972 syncTouch(when, true);
1973 }
1974
Jeff Brownb51719b2010-07-29 18:18:33 -07001975 { // acquire lock
1976 AutoMutex _l(mLock);
1977 initializeLocked();
1978 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001979
Jeff Brownb51719b2010-07-29 18:18:33 -07001980 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001981}
1982
1983void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001984 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07001985
1986 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001987 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1988
1989 if (! applyStandardPolicyActions(when, policyActions)) {
1990 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07001991 return; // event dropped
1992 }
1993
Jeff Brownb51719b2010-07-29 18:18:33 -07001994 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07001995
Jeff Browne57e8952010-07-23 21:28:06 -07001996 if (mParameters.useBadTouchFilter) {
1997 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07001998 havePointerIds = false;
1999 }
2000 }
2001
Jeff Browne57e8952010-07-23 21:28:06 -07002002 if (mParameters.useJumpyTouchFilter) {
2003 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002004 havePointerIds = false;
2005 }
2006 }
2007
2008 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002009 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002010 }
2011
Jeff Browne57e8952010-07-23 21:28:06 -07002012 TouchData temp;
2013 TouchData* savedTouch;
2014 if (mParameters.useAveragingTouchFilter) {
2015 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002016 savedTouch = & temp;
2017
Jeff Browne57e8952010-07-23 21:28:06 -07002018 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002019 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002020 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002021 }
2022
Jeff Brownb51719b2010-07-29 18:18:33 -07002023 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002024
Jeff Browne57e8952010-07-23 21:28:06 -07002025 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2026 if (touchResult == DISPATCH_TOUCH) {
2027 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002028 }
2029
Jeff Brownb51719b2010-07-29 18:18:33 -07002030 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002031
Jeff Browne57e8952010-07-23 21:28:06 -07002032 if (touchResult == DROP_STROKE) {
2033 mLastTouch.clear();
2034 } else {
2035 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002036 }
Jeff Browne839a582010-04-22 18:58:52 -07002037}
2038
Jeff Browne57e8952010-07-23 21:28:06 -07002039TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2040 nsecs_t when, uint32_t policyFlags) {
2041 int32_t keyEventAction, keyEventFlags;
2042 int32_t keyCode, scanCode, downTime;
2043 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002044
Jeff Brownb51719b2010-07-29 18:18:33 -07002045 { // acquire lock
2046 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002047
Jeff Brownb51719b2010-07-29 18:18:33 -07002048 // Update surface size and orientation, including virtual key positions.
2049 if (! configureSurfaceLocked()) {
2050 return DROP_STROKE;
2051 }
2052
2053 // Check for virtual key press.
2054 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002055 if (mCurrentTouch.pointerCount == 0) {
2056 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002057 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002058#if DEBUG_VIRTUAL_KEYS
2059 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2060 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2061#endif
2062 keyEventAction = AKEY_EVENT_ACTION_UP;
2063 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2064 touchResult = SKIP_TOUCH;
2065 goto DispatchVirtualKey;
2066 }
2067
2068 if (mCurrentTouch.pointerCount == 1) {
2069 int32_t x = mCurrentTouch.pointers[0].x;
2070 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002071 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2072 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002073 // Pointer is still within the space of the virtual key.
2074 return SKIP_TOUCH;
2075 }
2076 }
2077
2078 // Pointer left virtual key area or another pointer also went down.
2079 // Send key cancellation and drop the stroke so subsequent motions will be
2080 // considered fresh downs. This is useful when the user swipes away from the
2081 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002082 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002083#if DEBUG_VIRTUAL_KEYS
2084 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2085 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2086#endif
2087 keyEventAction = AKEY_EVENT_ACTION_UP;
2088 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2089 | AKEY_EVENT_FLAG_CANCELED;
2090 touchResult = DROP_STROKE;
2091 goto DispatchVirtualKey;
2092 } else {
2093 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2094 // Pointer just went down. Handle off-screen touches, if needed.
2095 int32_t x = mCurrentTouch.pointers[0].x;
2096 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002097 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002098 // If exactly one pointer went down, check for virtual key hit.
2099 // Otherwise we will drop the entire stroke.
2100 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002101 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002102 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002103 mLocked.currentVirtualKey.down = true;
2104 mLocked.currentVirtualKey.downTime = when;
2105 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2106 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002107#if DEBUG_VIRTUAL_KEYS
2108 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2109 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2110#endif
2111 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2112 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2113 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2114 touchResult = SKIP_TOUCH;
2115 goto DispatchVirtualKey;
2116 }
2117 }
2118 return DROP_STROKE;
2119 }
2120 }
2121 return DISPATCH_TOUCH;
2122 }
2123
2124 DispatchVirtualKey:
2125 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002126 keyCode = mLocked.currentVirtualKey.keyCode;
2127 scanCode = mLocked.currentVirtualKey.scanCode;
2128 downTime = mLocked.currentVirtualKey.downTime;
2129 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002130
2131 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002132 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
2133 keyCode, scanCode, downTime);
2134 return touchResult;
2135}
2136
2137void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
2138 int32_t keyEventAction, int32_t keyEventFlags,
2139 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07002140 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07002141
Jeff Brown5c1ed842010-07-14 18:48:53 -07002142 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Browne57e8952010-07-23 21:28:06 -07002143 getPolicy()->virtualKeyDownFeedback();
Jeff Brownf16c26d2010-07-02 15:37:36 -07002144 }
Jeff Browne839a582010-04-22 18:58:52 -07002145
Jeff Browne57e8952010-07-23 21:28:06 -07002146 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002147 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07002148
Jeff Browne57e8952010-07-23 21:28:06 -07002149 if (applyStandardPolicyActions(when, policyActions)) {
2150 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07002151 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2152 }
Jeff Browne839a582010-04-22 18:58:52 -07002153}
2154
Jeff Browne57e8952010-07-23 21:28:06 -07002155void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2156 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2157 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002158 if (currentPointerCount == 0 && lastPointerCount == 0) {
2159 return; // nothing to do!
2160 }
2161
Jeff Browne57e8952010-07-23 21:28:06 -07002162 BitSet32 currentIdBits = mCurrentTouch.idBits;
2163 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002164
2165 if (currentIdBits == lastIdBits) {
2166 // No pointer id changes so this is a move event.
2167 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002168 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002169 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002170 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002171 } else {
2172 // There may be pointers going up and pointers going down at the same time when pointer
2173 // ids are reported by the device driver.
2174 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2175 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2176 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002177 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002178
2179 while (! upIdBits.isEmpty()) {
2180 uint32_t upId = upIdBits.firstMarkedBit();
2181 upIdBits.clearBit(upId);
2182 BitSet32 oldActiveIdBits = activeIdBits;
2183 activeIdBits.clearBit(upId);
2184
2185 int32_t motionEventAction;
2186 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002187 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002188 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002189 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002190 }
2191
Jeff Browne57e8952010-07-23 21:28:06 -07002192 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002193 oldActiveIdBits, upId, pointerCount, motionEventAction);
2194 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002195 }
2196
2197 while (! downIdBits.isEmpty()) {
2198 uint32_t downId = downIdBits.firstMarkedBit();
2199 downIdBits.clearBit(downId);
2200 BitSet32 oldActiveIdBits = activeIdBits;
2201 activeIdBits.markBit(downId);
2202
2203 int32_t motionEventAction;
2204 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002205 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002206 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002207 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002208 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002209 }
2210
Jeff Brown38a7fab2010-08-30 03:02:23 -07002211 pointerCount += 1;
Jeff Browne57e8952010-07-23 21:28:06 -07002212 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002213 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002214 }
2215 }
2216}
2217
Jeff Browne57e8952010-07-23 21:28:06 -07002218void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002219 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002220 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002221 int32_t pointerIds[MAX_POINTERS];
2222 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002223 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002224 float xPrecision, yPrecision;
2225
2226 { // acquire lock
2227 AutoMutex _l(mLock);
2228
2229 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2230 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002231 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002232 uint32_t id = idBits.firstMarkedBit();
2233 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002234 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002235
Jeff Brown38a7fab2010-08-30 03:02:23 -07002236 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002237
Jeff Brown38a7fab2010-08-30 03:02:23 -07002238 // X and Y
2239 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2240 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002241
Jeff Brown38a7fab2010-08-30 03:02:23 -07002242 // ToolMajor and ToolMinor
2243 float toolMajor, toolMinor;
2244 switch (mCalibration.toolAreaCalibration) {
2245 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
2246 toolMajor = in.toolMajor * mLocked.geometricScale;
2247 if (mRawAxes.toolMinor.valid) {
2248 toolMinor = in.toolMinor * mLocked.geometricScale;
2249 } else {
2250 toolMinor = toolMajor;
2251 }
2252 break;
2253 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
2254 toolMajor = in.toolMajor != 0
2255 ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias
2256 : 0;
2257 if (mRawAxes.toolMinor.valid) {
2258 toolMinor = in.toolMinor != 0
2259 ? in.toolMinor * mLocked.toolAreaLinearScale
2260 + mLocked.toolAreaLinearBias
2261 : 0;
2262 } else {
2263 toolMinor = toolMajor;
2264 }
2265 break;
2266 default:
2267 toolMajor = 0;
2268 toolMinor = 0;
2269 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002270 }
2271
Jeff Brown38a7fab2010-08-30 03:02:23 -07002272 if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) {
2273 toolMajor /= pointerCount;
2274 toolMinor /= pointerCount;
2275 }
2276
2277 // Pressure
2278 float rawPressure;
2279 switch (mCalibration.pressureSource) {
2280 case Calibration::PRESSURE_SOURCE_PRESSURE:
2281 rawPressure = in.pressure;
2282 break;
2283 case Calibration::PRESSURE_SOURCE_TOUCH:
2284 rawPressure = in.touchMajor;
2285 break;
2286 default:
2287 rawPressure = 0;
2288 }
2289
2290 float pressure;
2291 switch (mCalibration.pressureCalibration) {
2292 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2293 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2294 pressure = rawPressure * mLocked.pressureScale;
2295 break;
2296 default:
2297 pressure = 1;
2298 break;
2299 }
2300
2301 // TouchMajor and TouchMinor
2302 float touchMajor, touchMinor;
2303 switch (mCalibration.touchAreaCalibration) {
2304 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
2305 touchMajor = in.touchMajor * mLocked.geometricScale;
2306 if (mRawAxes.touchMinor.valid) {
2307 touchMinor = in.touchMinor * mLocked.geometricScale;
2308 } else {
2309 touchMinor = touchMajor;
2310 }
2311 break;
2312 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
2313 touchMajor = toolMajor * pressure;
2314 touchMinor = toolMinor * pressure;
2315 break;
2316 default:
2317 touchMajor = 0;
2318 touchMinor = 0;
2319 break;
2320 }
2321
2322 if (touchMajor > toolMajor) {
2323 touchMajor = toolMajor;
2324 }
2325 if (touchMinor > toolMinor) {
2326 touchMinor = toolMinor;
2327 }
2328
2329 // Size
2330 float size;
2331 switch (mCalibration.sizeCalibration) {
2332 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2333 float rawSize = mRawAxes.toolMinor.valid
2334 ? avg(in.toolMajor, in.toolMinor)
2335 : in.toolMajor;
2336 size = rawSize * mLocked.sizeScale;
2337 break;
2338 }
2339 default:
2340 size = 0;
2341 break;
2342 }
2343
2344 // Orientation
2345 float orientation;
2346 switch (mCalibration.orientationCalibration) {
2347 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2348 orientation = in.orientation * mLocked.orientationScale;
2349 break;
2350 default:
2351 orientation = 0;
2352 }
2353
2354 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002355 switch (mLocked.surfaceOrientation) {
2356 case InputReaderPolicyInterface::ROTATION_90: {
2357 float xTemp = x;
2358 x = y;
2359 y = mLocked.surfaceWidth - xTemp;
2360 orientation -= M_PI_2;
2361 if (orientation < - M_PI_2) {
2362 orientation += M_PI;
2363 }
2364 break;
2365 }
2366 case InputReaderPolicyInterface::ROTATION_180: {
2367 x = mLocked.surfaceWidth - x;
2368 y = mLocked.surfaceHeight - y;
2369 orientation = - orientation;
2370 break;
2371 }
2372 case InputReaderPolicyInterface::ROTATION_270: {
2373 float xTemp = x;
2374 x = mLocked.surfaceHeight - y;
2375 y = xTemp;
2376 orientation += M_PI_2;
2377 if (orientation > M_PI_2) {
2378 orientation -= M_PI;
2379 }
2380 break;
2381 }
2382 }
2383
Jeff Brown38a7fab2010-08-30 03:02:23 -07002384 // Write output coords.
2385 PointerCoords& out = pointerCoords[outIndex];
2386 out.x = x;
2387 out.y = y;
2388 out.pressure = pressure;
2389 out.size = size;
2390 out.touchMajor = touchMajor;
2391 out.touchMinor = touchMinor;
2392 out.toolMajor = toolMajor;
2393 out.toolMinor = toolMinor;
2394 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002395
Jeff Brown38a7fab2010-08-30 03:02:23 -07002396 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002397
2398 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002399 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002400 }
Jeff Browne839a582010-04-22 18:58:52 -07002401 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002402
2403 // Check edge flags by looking only at the first pointer since the flags are
2404 // global to the event.
2405 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2406 if (pointerCoords[0].x <= 0) {
2407 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2408 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2409 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2410 }
2411 if (pointerCoords[0].y <= 0) {
2412 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2413 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2414 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2415 }
Jeff Browne839a582010-04-22 18:58:52 -07002416 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002417
2418 xPrecision = mLocked.orientedXPrecision;
2419 yPrecision = mLocked.orientedYPrecision;
2420 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002421
Jeff Browne57e8952010-07-23 21:28:06 -07002422 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002423 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002424 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002425 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002426}
2427
Jeff Brownb51719b2010-07-29 18:18:33 -07002428bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002429 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2430 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2431 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002432 }
Jeff Browne57e8952010-07-23 21:28:06 -07002433 return true;
2434}
2435
Jeff Brownb51719b2010-07-29 18:18:33 -07002436const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2437 int32_t x, int32_t y) {
2438 size_t numVirtualKeys = mLocked.virtualKeys.size();
2439 for (size_t i = 0; i < numVirtualKeys; i++) {
2440 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002441
2442#if DEBUG_VIRTUAL_KEYS
2443 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2444 "left=%d, top=%d, right=%d, bottom=%d",
2445 x, y,
2446 virtualKey.keyCode, virtualKey.scanCode,
2447 virtualKey.hitLeft, virtualKey.hitTop,
2448 virtualKey.hitRight, virtualKey.hitBottom);
2449#endif
2450
2451 if (virtualKey.isHit(x, y)) {
2452 return & virtualKey;
2453 }
2454 }
2455
2456 return NULL;
2457}
2458
2459void TouchInputMapper::calculatePointerIds() {
2460 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2461 uint32_t lastPointerCount = mLastTouch.pointerCount;
2462
2463 if (currentPointerCount == 0) {
2464 // No pointers to assign.
2465 mCurrentTouch.idBits.clear();
2466 } else if (lastPointerCount == 0) {
2467 // All pointers are new.
2468 mCurrentTouch.idBits.clear();
2469 for (uint32_t i = 0; i < currentPointerCount; i++) {
2470 mCurrentTouch.pointers[i].id = i;
2471 mCurrentTouch.idToIndex[i] = i;
2472 mCurrentTouch.idBits.markBit(i);
2473 }
2474 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2475 // Only one pointer and no change in count so it must have the same id as before.
2476 uint32_t id = mLastTouch.pointers[0].id;
2477 mCurrentTouch.pointers[0].id = id;
2478 mCurrentTouch.idToIndex[id] = 0;
2479 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2480 } else {
2481 // General case.
2482 // We build a heap of squared euclidean distances between current and last pointers
2483 // associated with the current and last pointer indices. Then, we find the best
2484 // match (by distance) for each current pointer.
2485 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2486
2487 uint32_t heapSize = 0;
2488 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2489 currentPointerIndex++) {
2490 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2491 lastPointerIndex++) {
2492 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2493 - mLastTouch.pointers[lastPointerIndex].x;
2494 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2495 - mLastTouch.pointers[lastPointerIndex].y;
2496
2497 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2498
2499 // Insert new element into the heap (sift up).
2500 heap[heapSize].currentPointerIndex = currentPointerIndex;
2501 heap[heapSize].lastPointerIndex = lastPointerIndex;
2502 heap[heapSize].distance = distance;
2503 heapSize += 1;
2504 }
2505 }
2506
2507 // Heapify
2508 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2509 startIndex -= 1;
2510 for (uint32_t parentIndex = startIndex; ;) {
2511 uint32_t childIndex = parentIndex * 2 + 1;
2512 if (childIndex >= heapSize) {
2513 break;
2514 }
2515
2516 if (childIndex + 1 < heapSize
2517 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2518 childIndex += 1;
2519 }
2520
2521 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2522 break;
2523 }
2524
2525 swap(heap[parentIndex], heap[childIndex]);
2526 parentIndex = childIndex;
2527 }
2528 }
2529
2530#if DEBUG_POINTER_ASSIGNMENT
2531 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2532 for (size_t i = 0; i < heapSize; i++) {
2533 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2534 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2535 heap[i].distance);
2536 }
2537#endif
2538
2539 // Pull matches out by increasing order of distance.
2540 // To avoid reassigning pointers that have already been matched, the loop keeps track
2541 // of which last and current pointers have been matched using the matchedXXXBits variables.
2542 // It also tracks the used pointer id bits.
2543 BitSet32 matchedLastBits(0);
2544 BitSet32 matchedCurrentBits(0);
2545 BitSet32 usedIdBits(0);
2546 bool first = true;
2547 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2548 for (;;) {
2549 if (first) {
2550 // The first time through the loop, we just consume the root element of
2551 // the heap (the one with smallest distance).
2552 first = false;
2553 } else {
2554 // Previous iterations consumed the root element of the heap.
2555 // Pop root element off of the heap (sift down).
2556 heapSize -= 1;
2557 assert(heapSize > 0);
2558
2559 // Sift down.
2560 heap[0] = heap[heapSize];
2561 for (uint32_t parentIndex = 0; ;) {
2562 uint32_t childIndex = parentIndex * 2 + 1;
2563 if (childIndex >= heapSize) {
2564 break;
2565 }
2566
2567 if (childIndex + 1 < heapSize
2568 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2569 childIndex += 1;
2570 }
2571
2572 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2573 break;
2574 }
2575
2576 swap(heap[parentIndex], heap[childIndex]);
2577 parentIndex = childIndex;
2578 }
2579
2580#if DEBUG_POINTER_ASSIGNMENT
2581 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2582 for (size_t i = 0; i < heapSize; i++) {
2583 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2584 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2585 heap[i].distance);
2586 }
2587#endif
2588 }
2589
2590 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2591 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2592
2593 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2594 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2595
2596 matchedCurrentBits.markBit(currentPointerIndex);
2597 matchedLastBits.markBit(lastPointerIndex);
2598
2599 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2600 mCurrentTouch.pointers[currentPointerIndex].id = id;
2601 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2602 usedIdBits.markBit(id);
2603
2604#if DEBUG_POINTER_ASSIGNMENT
2605 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2606 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2607#endif
2608 break;
2609 }
2610 }
2611
2612 // Assign fresh ids to new pointers.
2613 if (currentPointerCount > lastPointerCount) {
2614 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2615 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2616 uint32_t id = usedIdBits.firstUnmarkedBit();
2617
2618 mCurrentTouch.pointers[currentPointerIndex].id = id;
2619 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2620 usedIdBits.markBit(id);
2621
2622#if DEBUG_POINTER_ASSIGNMENT
2623 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2624 currentPointerIndex, id);
2625#endif
2626
2627 if (--i == 0) break; // done
2628 matchedCurrentBits.markBit(currentPointerIndex);
2629 }
2630 }
2631
2632 // Fix id bits.
2633 mCurrentTouch.idBits = usedIdBits;
2634 }
2635}
2636
2637/* Special hack for devices that have bad screen data: if one of the
2638 * points has moved more than a screen height from the last position,
2639 * then drop it. */
2640bool TouchInputMapper::applyBadTouchFilter() {
2641 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002642 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002643 return false;
2644 }
2645
2646 uint32_t pointerCount = mCurrentTouch.pointerCount;
2647
2648 // Nothing to do if there are no points.
2649 if (pointerCount == 0) {
2650 return false;
2651 }
2652
2653 // Don't do anything if a finger is going down or up. We run
2654 // here before assigning pointer IDs, so there isn't a good
2655 // way to do per-finger matching.
2656 if (pointerCount != mLastTouch.pointerCount) {
2657 return false;
2658 }
2659
2660 // We consider a single movement across more than a 7/16 of
2661 // the long size of the screen to be bad. This was a magic value
2662 // determined by looking at the maximum distance it is feasible
2663 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002664 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002665
2666 // XXX The original code in InputDevice.java included commented out
2667 // code for testing the X axis. Note that when we drop a point
2668 // we don't actually restore the old X either. Strange.
2669 // The old code also tries to track when bad points were previously
2670 // detected but it turns out that due to the placement of a "break"
2671 // at the end of the loop, we never set mDroppedBadPoint to true
2672 // so it is effectively dead code.
2673 // Need to figure out if the old code is busted or just overcomplicated
2674 // but working as intended.
2675
2676 // Look through all new points and see if any are farther than
2677 // acceptable from all previous points.
2678 for (uint32_t i = pointerCount; i-- > 0; ) {
2679 int32_t y = mCurrentTouch.pointers[i].y;
2680 int32_t closestY = INT_MAX;
2681 int32_t closestDeltaY = 0;
2682
2683#if DEBUG_HACKS
2684 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2685#endif
2686
2687 for (uint32_t j = pointerCount; j-- > 0; ) {
2688 int32_t lastY = mLastTouch.pointers[j].y;
2689 int32_t deltaY = abs(y - lastY);
2690
2691#if DEBUG_HACKS
2692 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2693 j, lastY, deltaY);
2694#endif
2695
2696 if (deltaY < maxDeltaY) {
2697 goto SkipSufficientlyClosePoint;
2698 }
2699 if (deltaY < closestDeltaY) {
2700 closestDeltaY = deltaY;
2701 closestY = lastY;
2702 }
2703 }
2704
2705 // Must not have found a close enough match.
2706#if DEBUG_HACKS
2707 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2708 i, y, closestY, closestDeltaY, maxDeltaY);
2709#endif
2710
2711 mCurrentTouch.pointers[i].y = closestY;
2712 return true; // XXX original code only corrects one point
2713
2714 SkipSufficientlyClosePoint: ;
2715 }
2716
2717 // No change.
2718 return false;
2719}
2720
2721/* Special hack for devices that have bad screen data: drop points where
2722 * the coordinate value for one axis has jumped to the other pointer's location.
2723 */
2724bool TouchInputMapper::applyJumpyTouchFilter() {
2725 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002726 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002727 return false;
2728 }
2729
2730 uint32_t pointerCount = mCurrentTouch.pointerCount;
2731 if (mLastTouch.pointerCount != pointerCount) {
2732#if DEBUG_HACKS
2733 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2734 mLastTouch.pointerCount, pointerCount);
2735 for (uint32_t i = 0; i < pointerCount; i++) {
2736 LOGD(" Pointer %d (%d, %d)", i,
2737 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2738 }
2739#endif
2740
2741 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2742 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2743 // Just drop the first few events going from 1 to 2 pointers.
2744 // They're bad often enough that they're not worth considering.
2745 mCurrentTouch.pointerCount = 1;
2746 mJumpyTouchFilter.jumpyPointsDropped += 1;
2747
2748#if DEBUG_HACKS
2749 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2750#endif
2751 return true;
2752 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2753 // The event when we go from 2 -> 1 tends to be messed up too
2754 mCurrentTouch.pointerCount = 2;
2755 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2756 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2757 mJumpyTouchFilter.jumpyPointsDropped += 1;
2758
2759#if DEBUG_HACKS
2760 for (int32_t i = 0; i < 2; i++) {
2761 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2762 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2763 }
2764#endif
2765 return true;
2766 }
2767 }
2768 // Reset jumpy points dropped on other transitions or if limit exceeded.
2769 mJumpyTouchFilter.jumpyPointsDropped = 0;
2770
2771#if DEBUG_HACKS
2772 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2773#endif
2774 return false;
2775 }
2776
2777 // We have the same number of pointers as last time.
2778 // A 'jumpy' point is one where the coordinate value for one axis
2779 // has jumped to the other pointer's location. No need to do anything
2780 // else if we only have one pointer.
2781 if (pointerCount < 2) {
2782 return false;
2783 }
2784
2785 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002786 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002787
2788 // We only replace the single worst jumpy point as characterized by pointer distance
2789 // in a single axis.
2790 int32_t badPointerIndex = -1;
2791 int32_t badPointerReplacementIndex = -1;
2792 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2793
2794 for (uint32_t i = pointerCount; i-- > 0; ) {
2795 int32_t x = mCurrentTouch.pointers[i].x;
2796 int32_t y = mCurrentTouch.pointers[i].y;
2797
2798#if DEBUG_HACKS
2799 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2800#endif
2801
2802 // Check if a touch point is too close to another's coordinates
2803 bool dropX = false, dropY = false;
2804 for (uint32_t j = 0; j < pointerCount; j++) {
2805 if (i == j) {
2806 continue;
2807 }
2808
2809 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2810 dropX = true;
2811 break;
2812 }
2813
2814 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2815 dropY = true;
2816 break;
2817 }
2818 }
2819 if (! dropX && ! dropY) {
2820 continue; // not jumpy
2821 }
2822
2823 // Find a replacement candidate by comparing with older points on the
2824 // complementary (non-jumpy) axis.
2825 int32_t distance = INT_MIN; // distance to be corrected
2826 int32_t replacementIndex = -1;
2827
2828 if (dropX) {
2829 // X looks too close. Find an older replacement point with a close Y.
2830 int32_t smallestDeltaY = INT_MAX;
2831 for (uint32_t j = 0; j < pointerCount; j++) {
2832 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2833 if (deltaY < smallestDeltaY) {
2834 smallestDeltaY = deltaY;
2835 replacementIndex = j;
2836 }
2837 }
2838 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2839 } else {
2840 // Y looks too close. Find an older replacement point with a close X.
2841 int32_t smallestDeltaX = INT_MAX;
2842 for (uint32_t j = 0; j < pointerCount; j++) {
2843 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2844 if (deltaX < smallestDeltaX) {
2845 smallestDeltaX = deltaX;
2846 replacementIndex = j;
2847 }
2848 }
2849 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2850 }
2851
2852 // If replacing this pointer would correct a worse error than the previous ones
2853 // considered, then use this replacement instead.
2854 if (distance > badPointerDistance) {
2855 badPointerIndex = i;
2856 badPointerReplacementIndex = replacementIndex;
2857 badPointerDistance = distance;
2858 }
2859 }
2860
2861 // Correct the jumpy pointer if one was found.
2862 if (badPointerIndex >= 0) {
2863#if DEBUG_HACKS
2864 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2865 badPointerIndex,
2866 mLastTouch.pointers[badPointerReplacementIndex].x,
2867 mLastTouch.pointers[badPointerReplacementIndex].y);
2868#endif
2869
2870 mCurrentTouch.pointers[badPointerIndex].x =
2871 mLastTouch.pointers[badPointerReplacementIndex].x;
2872 mCurrentTouch.pointers[badPointerIndex].y =
2873 mLastTouch.pointers[badPointerReplacementIndex].y;
2874 mJumpyTouchFilter.jumpyPointsDropped += 1;
2875 return true;
2876 }
2877 }
2878
2879 mJumpyTouchFilter.jumpyPointsDropped = 0;
2880 return false;
2881}
2882
2883/* Special hack for devices that have bad screen data: aggregate and
2884 * compute averages of the coordinate data, to reduce the amount of
2885 * jitter seen by applications. */
2886void TouchInputMapper::applyAveragingTouchFilter() {
2887 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2888 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2889 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2890 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002891 int32_t pressure;
2892 switch (mCalibration.pressureSource) {
2893 case Calibration::PRESSURE_SOURCE_PRESSURE:
2894 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2895 break;
2896 case Calibration::PRESSURE_SOURCE_TOUCH:
2897 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2898 break;
2899 default:
2900 pressure = 1;
2901 break;
2902 }
Jeff Browne57e8952010-07-23 21:28:06 -07002903
2904 if (mLastTouch.idBits.hasBit(id)) {
2905 // Pointer was down before and is still down now.
2906 // Compute average over history trace.
2907 uint32_t start = mAveragingTouchFilter.historyStart[id];
2908 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2909
2910 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2911 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2912 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2913
2914#if DEBUG_HACKS
2915 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2916 id, distance);
2917#endif
2918
2919 if (distance < AVERAGING_DISTANCE_LIMIT) {
2920 // Increment end index in preparation for recording new historical data.
2921 end += 1;
2922 if (end > AVERAGING_HISTORY_SIZE) {
2923 end = 0;
2924 }
2925
2926 // If the end index has looped back to the start index then we have filled
2927 // the historical trace up to the desired size so we drop the historical
2928 // data at the start of the trace.
2929 if (end == start) {
2930 start += 1;
2931 if (start > AVERAGING_HISTORY_SIZE) {
2932 start = 0;
2933 }
2934 }
2935
2936 // Add the raw data to the historical trace.
2937 mAveragingTouchFilter.historyStart[id] = start;
2938 mAveragingTouchFilter.historyEnd[id] = end;
2939 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2940 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2941 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2942
2943 // Average over all historical positions in the trace by total pressure.
2944 int32_t averagedX = 0;
2945 int32_t averagedY = 0;
2946 int32_t totalPressure = 0;
2947 for (;;) {
2948 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2949 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2950 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2951 .pointers[id].pressure;
2952
2953 averagedX += historicalX * historicalPressure;
2954 averagedY += historicalY * historicalPressure;
2955 totalPressure += historicalPressure;
2956
2957 if (start == end) {
2958 break;
2959 }
2960
2961 start += 1;
2962 if (start > AVERAGING_HISTORY_SIZE) {
2963 start = 0;
2964 }
2965 }
2966
Jeff Brown38a7fab2010-08-30 03:02:23 -07002967 if (totalPressure != 0) {
2968 averagedX /= totalPressure;
2969 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07002970
2971#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07002972 LOGD("AveragingTouchFilter: Pointer id %d - "
2973 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2974 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07002975#endif
2976
Jeff Brown38a7fab2010-08-30 03:02:23 -07002977 mCurrentTouch.pointers[currentIndex].x = averagedX;
2978 mCurrentTouch.pointers[currentIndex].y = averagedY;
2979 }
Jeff Browne57e8952010-07-23 21:28:06 -07002980 } else {
2981#if DEBUG_HACKS
2982 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2983#endif
2984 }
2985 } else {
2986#if DEBUG_HACKS
2987 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2988#endif
2989 }
2990
2991 // Reset pointer history.
2992 mAveragingTouchFilter.historyStart[id] = 0;
2993 mAveragingTouchFilter.historyEnd[id] = 0;
2994 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2995 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2996 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
2997 }
2998}
2999
3000int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003001 { // acquire lock
3002 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003003
Jeff Brownb51719b2010-07-29 18:18:33 -07003004 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003005 return AKEY_STATE_VIRTUAL;
3006 }
3007
Jeff Brownb51719b2010-07-29 18:18:33 -07003008 size_t numVirtualKeys = mLocked.virtualKeys.size();
3009 for (size_t i = 0; i < numVirtualKeys; i++) {
3010 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003011 if (virtualKey.keyCode == keyCode) {
3012 return AKEY_STATE_UP;
3013 }
3014 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003015 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003016
3017 return AKEY_STATE_UNKNOWN;
3018}
3019
3020int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003021 { // acquire lock
3022 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003023
Jeff Brownb51719b2010-07-29 18:18:33 -07003024 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003025 return AKEY_STATE_VIRTUAL;
3026 }
3027
Jeff Brownb51719b2010-07-29 18:18:33 -07003028 size_t numVirtualKeys = mLocked.virtualKeys.size();
3029 for (size_t i = 0; i < numVirtualKeys; i++) {
3030 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003031 if (virtualKey.scanCode == scanCode) {
3032 return AKEY_STATE_UP;
3033 }
3034 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003035 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003036
3037 return AKEY_STATE_UNKNOWN;
3038}
3039
3040bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3041 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003042 { // acquire lock
3043 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003044
Jeff Brownb51719b2010-07-29 18:18:33 -07003045 size_t numVirtualKeys = mLocked.virtualKeys.size();
3046 for (size_t i = 0; i < numVirtualKeys; i++) {
3047 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003048
3049 for (size_t i = 0; i < numCodes; i++) {
3050 if (virtualKey.keyCode == keyCodes[i]) {
3051 outFlags[i] = 1;
3052 }
3053 }
3054 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003055 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003056
3057 return true;
3058}
3059
3060
3061// --- SingleTouchInputMapper ---
3062
3063SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3064 TouchInputMapper(device, associatedDisplayId) {
3065 initialize();
3066}
3067
3068SingleTouchInputMapper::~SingleTouchInputMapper() {
3069}
3070
3071void SingleTouchInputMapper::initialize() {
3072 mAccumulator.clear();
3073
3074 mDown = false;
3075 mX = 0;
3076 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003077 mPressure = 0; // default to 0 for devices that don't report pressure
3078 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003079}
3080
3081void SingleTouchInputMapper::reset() {
3082 TouchInputMapper::reset();
3083
Jeff Browne57e8952010-07-23 21:28:06 -07003084 initialize();
3085 }
3086
3087void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3088 switch (rawEvent->type) {
3089 case EV_KEY:
3090 switch (rawEvent->scanCode) {
3091 case BTN_TOUCH:
3092 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3093 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003094 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3095 // not have received valid position information yet. This logic assumes that
3096 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003097 break;
3098 }
3099 break;
3100
3101 case EV_ABS:
3102 switch (rawEvent->scanCode) {
3103 case ABS_X:
3104 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3105 mAccumulator.absX = rawEvent->value;
3106 break;
3107 case ABS_Y:
3108 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3109 mAccumulator.absY = rawEvent->value;
3110 break;
3111 case ABS_PRESSURE:
3112 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3113 mAccumulator.absPressure = rawEvent->value;
3114 break;
3115 case ABS_TOOL_WIDTH:
3116 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3117 mAccumulator.absToolWidth = rawEvent->value;
3118 break;
3119 }
3120 break;
3121
3122 case EV_SYN:
3123 switch (rawEvent->scanCode) {
3124 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003125 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003126 break;
3127 }
3128 break;
3129 }
3130}
3131
3132void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003133 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003134 if (fields == 0) {
3135 return; // no new state changes, so nothing to do
3136 }
Jeff Browne57e8952010-07-23 21:28:06 -07003137
3138 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3139 mDown = mAccumulator.btnTouch;
3140 }
3141
3142 if (fields & Accumulator::FIELD_ABS_X) {
3143 mX = mAccumulator.absX;
3144 }
3145
3146 if (fields & Accumulator::FIELD_ABS_Y) {
3147 mY = mAccumulator.absY;
3148 }
3149
3150 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3151 mPressure = mAccumulator.absPressure;
3152 }
3153
3154 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003155 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003156 }
3157
3158 mCurrentTouch.clear();
3159
3160 if (mDown) {
3161 mCurrentTouch.pointerCount = 1;
3162 mCurrentTouch.pointers[0].id = 0;
3163 mCurrentTouch.pointers[0].x = mX;
3164 mCurrentTouch.pointers[0].y = mY;
3165 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003166 mCurrentTouch.pointers[0].touchMajor = 0;
3167 mCurrentTouch.pointers[0].touchMinor = 0;
3168 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3169 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003170 mCurrentTouch.pointers[0].orientation = 0;
3171 mCurrentTouch.idToIndex[0] = 0;
3172 mCurrentTouch.idBits.markBit(0);
3173 }
3174
3175 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003176
3177 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003178}
3179
Jeff Brown38a7fab2010-08-30 03:02:23 -07003180void SingleTouchInputMapper::configureRawAxes() {
3181 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003182
Jeff Brown38a7fab2010-08-30 03:02:23 -07003183 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3184 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3185 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3186 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003187}
3188
3189
3190// --- MultiTouchInputMapper ---
3191
3192MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3193 TouchInputMapper(device, associatedDisplayId) {
3194 initialize();
3195}
3196
3197MultiTouchInputMapper::~MultiTouchInputMapper() {
3198}
3199
3200void MultiTouchInputMapper::initialize() {
3201 mAccumulator.clear();
3202}
3203
3204void MultiTouchInputMapper::reset() {
3205 TouchInputMapper::reset();
3206
Jeff Browne57e8952010-07-23 21:28:06 -07003207 initialize();
3208}
3209
3210void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3211 switch (rawEvent->type) {
3212 case EV_ABS: {
3213 uint32_t pointerIndex = mAccumulator.pointerCount;
3214 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3215
3216 switch (rawEvent->scanCode) {
3217 case ABS_MT_POSITION_X:
3218 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3219 pointer->absMTPositionX = rawEvent->value;
3220 break;
3221 case ABS_MT_POSITION_Y:
3222 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3223 pointer->absMTPositionY = rawEvent->value;
3224 break;
3225 case ABS_MT_TOUCH_MAJOR:
3226 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3227 pointer->absMTTouchMajor = rawEvent->value;
3228 break;
3229 case ABS_MT_TOUCH_MINOR:
3230 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3231 pointer->absMTTouchMinor = rawEvent->value;
3232 break;
3233 case ABS_MT_WIDTH_MAJOR:
3234 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3235 pointer->absMTWidthMajor = rawEvent->value;
3236 break;
3237 case ABS_MT_WIDTH_MINOR:
3238 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3239 pointer->absMTWidthMinor = rawEvent->value;
3240 break;
3241 case ABS_MT_ORIENTATION:
3242 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3243 pointer->absMTOrientation = rawEvent->value;
3244 break;
3245 case ABS_MT_TRACKING_ID:
3246 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3247 pointer->absMTTrackingId = rawEvent->value;
3248 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003249 case ABS_MT_PRESSURE:
3250 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3251 pointer->absMTPressure = rawEvent->value;
3252 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003253 }
3254 break;
3255 }
3256
3257 case EV_SYN:
3258 switch (rawEvent->scanCode) {
3259 case SYN_MT_REPORT: {
3260 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3261 uint32_t pointerIndex = mAccumulator.pointerCount;
3262
3263 if (mAccumulator.pointers[pointerIndex].fields) {
3264 if (pointerIndex == MAX_POINTERS) {
3265 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3266 MAX_POINTERS);
3267 } else {
3268 pointerIndex += 1;
3269 mAccumulator.pointerCount = pointerIndex;
3270 }
3271 }
3272
3273 mAccumulator.pointers[pointerIndex].clear();
3274 break;
3275 }
3276
3277 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003278 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003279 break;
3280 }
3281 break;
3282 }
3283}
3284
3285void MultiTouchInputMapper::sync(nsecs_t when) {
3286 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003287 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003288
Jeff Browne57e8952010-07-23 21:28:06 -07003289 uint32_t inCount = mAccumulator.pointerCount;
3290 uint32_t outCount = 0;
3291 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003292
Jeff Browne57e8952010-07-23 21:28:06 -07003293 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003294
Jeff Browne57e8952010-07-23 21:28:06 -07003295 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003296 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3297 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003298
Jeff Browne57e8952010-07-23 21:28:06 -07003299 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003300 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3301 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003302 continue;
3303 }
3304
Jeff Brownd64c8552010-08-17 20:38:35 -07003305 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3306 outPointer.x = inPointer.absMTPositionX;
3307 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003308
Jeff Brown38a7fab2010-08-30 03:02:23 -07003309 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3310 if (inPointer.absMTPressure <= 0) {
3311 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brownd64c8552010-08-17 20:38:35 -07003312 // a pointer up. Drop this finger.
3313 continue;
3314 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003315 outPointer.pressure = inPointer.absMTPressure;
3316 } else {
3317 // Default pressure to 0 if absent.
3318 outPointer.pressure = 0;
3319 }
3320
3321 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3322 if (inPointer.absMTTouchMajor <= 0) {
3323 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3324 // a pointer going up. Drop this finger.
3325 continue;
3326 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003327 outPointer.touchMajor = inPointer.absMTTouchMajor;
3328 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003329 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003330 outPointer.touchMajor = 0;
3331 }
Jeff Browne839a582010-04-22 18:58:52 -07003332
Jeff Brownd64c8552010-08-17 20:38:35 -07003333 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3334 outPointer.touchMinor = inPointer.absMTTouchMinor;
3335 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003336 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003337 outPointer.touchMinor = outPointer.touchMajor;
3338 }
Jeff Browne839a582010-04-22 18:58:52 -07003339
Jeff Brownd64c8552010-08-17 20:38:35 -07003340 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3341 outPointer.toolMajor = inPointer.absMTWidthMajor;
3342 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003343 // Default tool area to 0 if absent.
3344 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003345 }
Jeff Browne839a582010-04-22 18:58:52 -07003346
Jeff Brownd64c8552010-08-17 20:38:35 -07003347 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3348 outPointer.toolMinor = inPointer.absMTWidthMinor;
3349 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003350 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003351 outPointer.toolMinor = outPointer.toolMajor;
3352 }
3353
3354 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3355 outPointer.orientation = inPointer.absMTOrientation;
3356 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003357 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003358 outPointer.orientation = 0;
3359 }
3360
Jeff Brown38a7fab2010-08-30 03:02:23 -07003361 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003362 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003363 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3364 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003365
Jeff Browne57e8952010-07-23 21:28:06 -07003366 if (id > MAX_POINTER_ID) {
3367#if DEBUG_POINTERS
3368 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003369 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003370 id, MAX_POINTER_ID);
3371#endif
3372 havePointerIds = false;
3373 }
3374 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003375 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003376 mCurrentTouch.idToIndex[id] = outCount;
3377 mCurrentTouch.idBits.markBit(id);
3378 }
3379 } else {
3380 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003381 }
3382 }
Jeff Browne839a582010-04-22 18:58:52 -07003383
Jeff Browne57e8952010-07-23 21:28:06 -07003384 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003385 }
3386
Jeff Browne57e8952010-07-23 21:28:06 -07003387 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003388
Jeff Browne57e8952010-07-23 21:28:06 -07003389 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003390
3391 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003392}
3393
Jeff Brown38a7fab2010-08-30 03:02:23 -07003394void MultiTouchInputMapper::configureRawAxes() {
3395 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003396
Jeff Brown38a7fab2010-08-30 03:02:23 -07003397 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3398 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3399 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3400 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3401 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3402 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3403 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3404 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003405}
3406
Jeff Browne839a582010-04-22 18:58:52 -07003407
3408} // namespace android