blob: 1d35e10ffbed22afb4d376fe3012a8b7ef72a733 [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 " "
Jeff Brown26c94ff2010-09-30 14:33:04 -070036#define INDENT2 " "
37#define INDENT3 " "
38#define INDENT4 " "
Jeff Brown38a7fab2010-08-30 03:02:23 -070039
Jeff Browne839a582010-04-22 18:58:52 -070040namespace android {
41
42// --- Static Functions ---
43
44template<typename T>
45inline static T abs(const T& value) {
46 return value < 0 ? - value : value;
47}
48
49template<typename T>
50inline static T min(const T& a, const T& b) {
51 return a < b ? a : b;
52}
53
Jeff Brownf4a4ec22010-06-16 01:53:36 -070054template<typename T>
55inline static void swap(T& a, T& b) {
56 T temp = a;
57 a = b;
58 b = temp;
59}
60
Jeff Brown38a7fab2010-08-30 03:02:23 -070061inline static float avg(float x, float y) {
62 return (x + y) / 2;
63}
64
65inline static float pythag(float x, float y) {
66 return sqrtf(x * x + y * y);
67}
68
Jeff Brown26c94ff2010-09-30 14:33:04 -070069static inline const char* toString(bool value) {
70 return value ? "true" : "false";
71}
72
Jeff Brownf4a4ec22010-06-16 01:53:36 -070073
Jeff Browne839a582010-04-22 18:58:52 -070074int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
75 int32_t mask;
76 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070077 case AKEYCODE_ALT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070078 mask = AMETA_ALT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070079 break;
Jeff Brown8575a872010-06-30 16:10:35 -070080 case AKEYCODE_ALT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070081 mask = AMETA_ALT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070082 break;
Jeff Brown8575a872010-06-30 16:10:35 -070083 case AKEYCODE_SHIFT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070084 mask = AMETA_SHIFT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070085 break;
Jeff Brown8575a872010-06-30 16:10:35 -070086 case AKEYCODE_SHIFT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070087 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070088 break;
Jeff Brown8575a872010-06-30 16:10:35 -070089 case AKEYCODE_SYM:
Jeff Brown5c1ed842010-07-14 18:48:53 -070090 mask = AMETA_SYM_ON;
Jeff Browne839a582010-04-22 18:58:52 -070091 break;
92 default:
93 return oldMetaState;
94 }
95
96 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brown5c1ed842010-07-14 18:48:53 -070097 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Browne839a582010-04-22 18:58:52 -070098
Jeff Brown5c1ed842010-07-14 18:48:53 -070099 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
100 newMetaState |= AMETA_ALT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700101 }
102
Jeff Brown5c1ed842010-07-14 18:48:53 -0700103 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
104 newMetaState |= AMETA_SHIFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700105 }
106
107 return newMetaState;
108}
109
110static const int32_t keyCodeRotationMap[][4] = {
111 // key codes enumerated counter-clockwise with the original (unrotated) key first
112 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brown8575a872010-06-30 16:10:35 -0700113 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
114 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
115 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
116 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Browne839a582010-04-22 18:58:52 -0700117};
118static const int keyCodeRotationMapSize =
119 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
120
121int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700122 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-04-22 18:58:52 -0700123 for (int i = 0; i < keyCodeRotationMapSize; i++) {
124 if (keyCode == keyCodeRotationMap[i][0]) {
125 return keyCodeRotationMap[i][orientation];
126 }
127 }
128 }
129 return keyCode;
130}
131
Jeff Browne57e8952010-07-23 21:28:06 -0700132static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
133 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
134}
135
Jeff Browne839a582010-04-22 18:58:52 -0700136
Jeff Brown38a7fab2010-08-30 03:02:23 -0700137// --- InputDeviceCalibration ---
138
139InputDeviceCalibration::InputDeviceCalibration() {
140}
141
142void InputDeviceCalibration::clear() {
143 mProperties.clear();
144}
145
146void InputDeviceCalibration::addProperty(const String8& key, const String8& value) {
147 mProperties.add(key, value);
148}
149
150bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const {
151 ssize_t index = mProperties.indexOfKey(key);
152 if (index < 0) {
153 return false;
154 }
155
156 outValue = mProperties.valueAt(index);
157 return true;
158}
159
160bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const {
161 String8 stringValue;
162 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
163 return false;
164 }
165
166 char* end;
167 int value = strtol(stringValue.string(), & end, 10);
168 if (*end != '\0') {
169 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.",
170 key.string(), stringValue.string());
171 return false;
172 }
173 outValue = value;
174 return true;
175}
176
177bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const {
178 String8 stringValue;
179 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
180 return false;
181 }
182
183 char* end;
184 float value = strtof(stringValue.string(), & end);
185 if (*end != '\0') {
186 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.",
187 key.string(), stringValue.string());
188 return false;
189 }
190 outValue = value;
191 return true;
192}
193
194
Jeff Browne839a582010-04-22 18:58:52 -0700195// --- InputReader ---
196
197InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700198 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700199 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Browne57e8952010-07-23 21:28:06 -0700200 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
201 mGlobalMetaState(0) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700202 configureExcludedDevices();
Jeff Browne57e8952010-07-23 21:28:06 -0700203 updateGlobalMetaState();
204 updateInputConfiguration();
Jeff Browne839a582010-04-22 18:58:52 -0700205}
206
207InputReader::~InputReader() {
208 for (size_t i = 0; i < mDevices.size(); i++) {
209 delete mDevices.valueAt(i);
210 }
211}
212
213void InputReader::loopOnce() {
214 RawEvent rawEvent;
Jeff Browne57e8952010-07-23 21:28:06 -0700215 mEventHub->getEvent(& rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700216
217#if DEBUG_RAW_EVENTS
218 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
219 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
220 rawEvent.value);
221#endif
222
223 process(& rawEvent);
224}
225
226void InputReader::process(const RawEvent* rawEvent) {
227 switch (rawEvent->type) {
228 case EventHubInterface::DEVICE_ADDED:
Jeff Browne57e8952010-07-23 21:28:06 -0700229 addDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700230 break;
231
232 case EventHubInterface::DEVICE_REMOVED:
Jeff Browne57e8952010-07-23 21:28:06 -0700233 removeDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700234 break;
235
Jeff Browne57e8952010-07-23 21:28:06 -0700236 default:
237 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700238 break;
239 }
240}
241
Jeff Browne57e8952010-07-23 21:28:06 -0700242void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
243 String8 name = mEventHub->getDeviceName(deviceId);
244 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
245
246 InputDevice* device = createDevice(deviceId, name, classes);
247 device->configure();
248
Jeff Brown38a7fab2010-08-30 03:02:23 -0700249 if (device->isIgnored()) {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700250 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", deviceId, name.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700251 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700252 LOGI("Device added: id=0x%x, name=%s, sources=%08x", deviceId, name.string(),
253 device->getSources());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700254 }
255
Jeff Browne57e8952010-07-23 21:28:06 -0700256 bool added = false;
257 { // acquire device registry writer lock
258 RWLock::AutoWLock _wl(mDeviceRegistryLock);
259
260 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
261 if (deviceIndex < 0) {
262 mDevices.add(deviceId, device);
263 added = true;
264 }
265 } // release device registry writer lock
266
267 if (! added) {
268 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
269 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700270 return;
271 }
272
Jeff Browne57e8952010-07-23 21:28:06 -0700273 handleConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700274}
275
Jeff Browne57e8952010-07-23 21:28:06 -0700276void InputReader::removeDevice(nsecs_t when, int32_t deviceId) {
277 bool removed = false;
278 InputDevice* device = NULL;
279 { // acquire device registry writer lock
280 RWLock::AutoWLock _wl(mDeviceRegistryLock);
281
282 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
283 if (deviceIndex >= 0) {
284 device = mDevices.valueAt(deviceIndex);
285 mDevices.removeItemsAt(deviceIndex, 1);
286 removed = true;
287 }
288 } // release device registry writer lock
289
290 if (! removed) {
291 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700292 return;
293 }
294
Jeff Browne57e8952010-07-23 21:28:06 -0700295 if (device->isIgnored()) {
296 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
297 device->getId(), device->getName().string());
298 } else {
299 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
300 device->getId(), device->getName().string(), device->getSources());
301 }
302
Jeff Brown38a7fab2010-08-30 03:02:23 -0700303 device->reset();
304
Jeff Browne57e8952010-07-23 21:28:06 -0700305 delete device;
306
307 handleConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700308}
309
Jeff Browne57e8952010-07-23 21:28:06 -0700310InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
311 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Browne839a582010-04-22 18:58:52 -0700312
Jeff Browne57e8952010-07-23 21:28:06 -0700313 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Browne839a582010-04-22 18:58:52 -0700314
Jeff Browne57e8952010-07-23 21:28:06 -0700315 // Switch-like devices.
316 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
317 device->addMapper(new SwitchInputMapper(device));
318 }
319
320 // Keyboard-like devices.
321 uint32_t keyboardSources = 0;
322 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
323 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
324 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
325 }
326 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
327 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
328 }
329 if (classes & INPUT_DEVICE_CLASS_DPAD) {
330 keyboardSources |= AINPUT_SOURCE_DPAD;
331 }
Jeff Browne57e8952010-07-23 21:28:06 -0700332
333 if (keyboardSources != 0) {
334 device->addMapper(new KeyboardInputMapper(device,
335 associatedDisplayId, keyboardSources, keyboardType));
336 }
337
338 // Trackball-like devices.
339 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
340 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
341 }
342
343 // Touchscreen-like devices.
344 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
345 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
346 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
347 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
348 }
349
350 return device;
351}
352
353void InputReader::consumeEvent(const RawEvent* rawEvent) {
354 int32_t deviceId = rawEvent->deviceId;
355
356 { // acquire device registry reader lock
357 RWLock::AutoRLock _rl(mDeviceRegistryLock);
358
359 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
360 if (deviceIndex < 0) {
361 LOGW("Discarding event for unknown deviceId %d.", deviceId);
362 return;
363 }
364
365 InputDevice* device = mDevices.valueAt(deviceIndex);
366 if (device->isIgnored()) {
367 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
368 return;
369 }
370
371 device->process(rawEvent);
372 } // release device registry reader lock
373}
374
375void InputReader::handleConfigurationChanged(nsecs_t when) {
376 // Reset global meta state because it depends on the list of all configured devices.
377 updateGlobalMetaState();
378
379 // Update input configuration.
380 updateInputConfiguration();
381
382 // Enqueue configuration changed.
383 mDispatcher->notifyConfigurationChanged(when);
384}
385
386void InputReader::configureExcludedDevices() {
387 Vector<String8> excludedDeviceNames;
388 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
389
390 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
391 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
392 }
393}
394
395void InputReader::updateGlobalMetaState() {
396 { // acquire state lock
397 AutoMutex _l(mStateLock);
398
399 mGlobalMetaState = 0;
400
401 { // acquire device registry reader lock
402 RWLock::AutoRLock _rl(mDeviceRegistryLock);
403
404 for (size_t i = 0; i < mDevices.size(); i++) {
405 InputDevice* device = mDevices.valueAt(i);
406 mGlobalMetaState |= device->getMetaState();
407 }
408 } // release device registry reader lock
409 } // release state lock
410}
411
412int32_t InputReader::getGlobalMetaState() {
413 { // acquire state lock
414 AutoMutex _l(mStateLock);
415
416 return mGlobalMetaState;
417 } // release state lock
418}
419
420void InputReader::updateInputConfiguration() {
421 { // acquire state lock
422 AutoMutex _l(mStateLock);
423
424 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
425 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
426 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
427 { // acquire device registry reader lock
428 RWLock::AutoRLock _rl(mDeviceRegistryLock);
429
430 InputDeviceInfo deviceInfo;
431 for (size_t i = 0; i < mDevices.size(); i++) {
432 InputDevice* device = mDevices.valueAt(i);
433 device->getDeviceInfo(& deviceInfo);
434 uint32_t sources = deviceInfo.getSources();
435
436 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
437 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
438 }
439 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
440 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
441 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
442 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
443 }
444 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
445 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Browne839a582010-04-22 18:58:52 -0700446 }
447 }
Jeff Browne57e8952010-07-23 21:28:06 -0700448 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700449
Jeff Browne57e8952010-07-23 21:28:06 -0700450 mInputConfiguration.touchScreen = touchScreenConfig;
451 mInputConfiguration.keyboard = keyboardConfig;
452 mInputConfiguration.navigation = navigationConfig;
453 } // release state lock
454}
455
456void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
457 { // acquire state lock
458 AutoMutex _l(mStateLock);
459
460 *outConfiguration = mInputConfiguration;
461 } // release state lock
462}
463
464status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
465 { // acquire device registry reader lock
466 RWLock::AutoRLock _rl(mDeviceRegistryLock);
467
468 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
469 if (deviceIndex < 0) {
470 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700471 }
472
Jeff Browne57e8952010-07-23 21:28:06 -0700473 InputDevice* device = mDevices.valueAt(deviceIndex);
474 if (device->isIgnored()) {
475 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700476 }
Jeff Browne57e8952010-07-23 21:28:06 -0700477
478 device->getDeviceInfo(outDeviceInfo);
479 return OK;
480 } // release device registy reader lock
481}
482
483void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
484 outDeviceIds.clear();
485
486 { // acquire device registry reader lock
487 RWLock::AutoRLock _rl(mDeviceRegistryLock);
488
489 size_t numDevices = mDevices.size();
490 for (size_t i = 0; i < numDevices; i++) {
491 InputDevice* device = mDevices.valueAt(i);
492 if (! device->isIgnored()) {
493 outDeviceIds.add(device->getId());
494 }
495 }
496 } // release device registy reader lock
497}
498
499int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
500 int32_t keyCode) {
501 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
502}
503
504int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
505 int32_t scanCode) {
506 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
507}
508
509int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
510 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
511}
512
513int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
514 GetStateFunc getStateFunc) {
515 { // acquire device registry reader lock
516 RWLock::AutoRLock _rl(mDeviceRegistryLock);
517
518 int32_t result = AKEY_STATE_UNKNOWN;
519 if (deviceId >= 0) {
520 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
521 if (deviceIndex >= 0) {
522 InputDevice* device = mDevices.valueAt(deviceIndex);
523 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
524 result = (device->*getStateFunc)(sourceMask, code);
525 }
526 }
527 } else {
528 size_t numDevices = mDevices.size();
529 for (size_t i = 0; i < numDevices; i++) {
530 InputDevice* device = mDevices.valueAt(i);
531 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
532 result = (device->*getStateFunc)(sourceMask, code);
533 if (result >= AKEY_STATE_DOWN) {
534 return result;
535 }
536 }
537 }
538 }
539 return result;
540 } // release device registy reader lock
541}
542
543bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
544 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
545 memset(outFlags, 0, numCodes);
546 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
547}
548
549bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
550 const int32_t* keyCodes, uint8_t* outFlags) {
551 { // acquire device registry reader lock
552 RWLock::AutoRLock _rl(mDeviceRegistryLock);
553 bool result = false;
554 if (deviceId >= 0) {
555 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
556 if (deviceIndex >= 0) {
557 InputDevice* device = mDevices.valueAt(deviceIndex);
558 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
559 result = device->markSupportedKeyCodes(sourceMask,
560 numCodes, keyCodes, outFlags);
561 }
562 }
563 } else {
564 size_t numDevices = mDevices.size();
565 for (size_t i = 0; i < numDevices; i++) {
566 InputDevice* device = mDevices.valueAt(i);
567 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
568 result |= device->markSupportedKeyCodes(sourceMask,
569 numCodes, keyCodes, outFlags);
570 }
571 }
572 }
573 return result;
574 } // release device registy reader lock
575}
576
Jeff Browna665ca82010-09-08 11:49:43 -0700577void InputReader::dump(String8& dump) {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700578 { // acquire device registry reader lock
579 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Browna665ca82010-09-08 11:49:43 -0700580
Jeff Brown26c94ff2010-09-30 14:33:04 -0700581 for (size_t i = 0; i < mDevices.size(); i++) {
582 mDevices.valueAt(i)->dump(dump);
Jeff Browna665ca82010-09-08 11:49:43 -0700583 }
Jeff Brown26c94ff2010-09-30 14:33:04 -0700584 } // release device registy reader lock
Jeff Browna665ca82010-09-08 11:49:43 -0700585}
586
Jeff Browne57e8952010-07-23 21:28:06 -0700587
588// --- InputReaderThread ---
589
590InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
591 Thread(/*canCallJava*/ true), mReader(reader) {
592}
593
594InputReaderThread::~InputReaderThread() {
595}
596
597bool InputReaderThread::threadLoop() {
598 mReader->loopOnce();
599 return true;
600}
601
602
603// --- InputDevice ---
604
605InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
606 mContext(context), mId(id), mName(name), mSources(0) {
607}
608
609InputDevice::~InputDevice() {
610 size_t numMappers = mMappers.size();
611 for (size_t i = 0; i < numMappers; i++) {
612 delete mMappers[i];
613 }
614 mMappers.clear();
615}
616
Jeff Brown26c94ff2010-09-30 14:33:04 -0700617static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
618 int32_t rangeType, const char* name) {
619 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
620 if (range) {
621 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
622 name, range->min, range->max, range->flat, range->fuzz);
623 }
624}
625
626void InputDevice::dump(String8& dump) {
627 InputDeviceInfo deviceInfo;
628 getDeviceInfo(& deviceInfo);
629
630 dump.appendFormat(INDENT "Device 0x%x: %s\n", deviceInfo.getId(),
631 deviceInfo.getName().string());
632 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
633 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
634 if (!deviceInfo.getMotionRanges().isEmpty()) {
635 dump.append(INDENT2 "Motion Ranges:\n");
636 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
637 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
638 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
639 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
640 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
641 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
642 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
643 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
644 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
645 }
646
647 size_t numMappers = mMappers.size();
648 for (size_t i = 0; i < numMappers; i++) {
649 InputMapper* mapper = mMappers[i];
650 mapper->dump(dump);
651 }
652}
653
Jeff Browne57e8952010-07-23 21:28:06 -0700654void InputDevice::addMapper(InputMapper* mapper) {
655 mMappers.add(mapper);
656}
657
658void InputDevice::configure() {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700659 if (! isIgnored()) {
660 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
661 }
662
Jeff Browne57e8952010-07-23 21:28:06 -0700663 mSources = 0;
664
665 size_t numMappers = mMappers.size();
666 for (size_t i = 0; i < numMappers; i++) {
667 InputMapper* mapper = mMappers[i];
668 mapper->configure();
669 mSources |= mapper->getSources();
Jeff Browne839a582010-04-22 18:58:52 -0700670 }
671}
672
Jeff Browne57e8952010-07-23 21:28:06 -0700673void InputDevice::reset() {
674 size_t numMappers = mMappers.size();
675 for (size_t i = 0; i < numMappers; i++) {
676 InputMapper* mapper = mMappers[i];
677 mapper->reset();
678 }
679}
Jeff Browne839a582010-04-22 18:58:52 -0700680
Jeff Browne57e8952010-07-23 21:28:06 -0700681void InputDevice::process(const RawEvent* rawEvent) {
682 size_t numMappers = mMappers.size();
683 for (size_t i = 0; i < numMappers; i++) {
684 InputMapper* mapper = mMappers[i];
685 mapper->process(rawEvent);
686 }
687}
Jeff Browne839a582010-04-22 18:58:52 -0700688
Jeff Browne57e8952010-07-23 21:28:06 -0700689void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
690 outDeviceInfo->initialize(mId, mName);
691
692 size_t numMappers = mMappers.size();
693 for (size_t i = 0; i < numMappers; i++) {
694 InputMapper* mapper = mMappers[i];
695 mapper->populateDeviceInfo(outDeviceInfo);
696 }
697}
698
699int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
700 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
701}
702
703int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
704 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
705}
706
707int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
708 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
709}
710
711int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
712 int32_t result = AKEY_STATE_UNKNOWN;
713 size_t numMappers = mMappers.size();
714 for (size_t i = 0; i < numMappers; i++) {
715 InputMapper* mapper = mMappers[i];
716 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
717 result = (mapper->*getStateFunc)(sourceMask, code);
718 if (result >= AKEY_STATE_DOWN) {
719 return result;
720 }
721 }
722 }
723 return result;
724}
725
726bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
727 const int32_t* keyCodes, uint8_t* outFlags) {
728 bool result = false;
729 size_t numMappers = mMappers.size();
730 for (size_t i = 0; i < numMappers; i++) {
731 InputMapper* mapper = mMappers[i];
732 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
733 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
734 }
735 }
736 return result;
737}
738
739int32_t InputDevice::getMetaState() {
740 int32_t result = 0;
741 size_t numMappers = mMappers.size();
742 for (size_t i = 0; i < numMappers; i++) {
743 InputMapper* mapper = mMappers[i];
744 result |= mapper->getMetaState();
745 }
746 return result;
747}
748
749
750// --- InputMapper ---
751
752InputMapper::InputMapper(InputDevice* device) :
753 mDevice(device), mContext(device->getContext()) {
754}
755
756InputMapper::~InputMapper() {
757}
758
759void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
760 info->addSource(getSources());
761}
762
Jeff Brown26c94ff2010-09-30 14:33:04 -0700763void InputMapper::dump(String8& dump) {
764}
765
Jeff Browne57e8952010-07-23 21:28:06 -0700766void 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
Jeff Brown26c94ff2010-09-30 14:33:04 -0700859void KeyboardInputMapper::dump(String8& dump) {
860 { // acquire lock
861 AutoMutex _l(mLock);
862 dump.append(INDENT2 "Keyboard Input Mapper:\n");
863 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
864 dump.appendFormat(INDENT3 "Sources: 0x%x\n", mSources);
865 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
866 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
867 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
868 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
869 } // release lock
870}
871
Jeff Browne57e8952010-07-23 21:28:06 -0700872void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700873 for (;;) {
874 int32_t keyCode, scanCode;
875 { // acquire lock
876 AutoMutex _l(mLock);
877
878 // Synthesize key up event on reset if keys are currently down.
879 if (mLocked.keyDowns.isEmpty()) {
880 initializeLocked();
881 break; // done
882 }
883
884 const KeyDown& keyDown = mLocked.keyDowns.top();
885 keyCode = keyDown.keyCode;
886 scanCode = keyDown.scanCode;
887 } // release lock
888
Jeff Browne57e8952010-07-23 21:28:06 -0700889 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700890 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700891 }
892
893 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700894 getContext()->updateGlobalMetaState();
895}
896
897void KeyboardInputMapper::process(const RawEvent* rawEvent) {
898 switch (rawEvent->type) {
899 case EV_KEY: {
900 int32_t scanCode = rawEvent->scanCode;
901 if (isKeyboardOrGamepadKey(scanCode)) {
902 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
903 rawEvent->flags);
904 }
905 break;
906 }
907 }
908}
909
910bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
911 return scanCode < BTN_MOUSE
912 || scanCode >= KEY_OK
913 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
914}
915
Jeff Brownb51719b2010-07-29 18:18:33 -0700916void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
917 int32_t scanCode, uint32_t policyFlags) {
918 int32_t newMetaState;
919 nsecs_t downTime;
920 bool metaStateChanged = false;
921
922 { // acquire lock
923 AutoMutex _l(mLock);
924
925 if (down) {
926 // Rotate key codes according to orientation if needed.
927 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
928 if (mAssociatedDisplayId >= 0) {
929 int32_t orientation;
930 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
931 return;
932 }
933
934 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700935 }
936
Jeff Brownb51719b2010-07-29 18:18:33 -0700937 // Add key down.
938 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
939 if (keyDownIndex >= 0) {
940 // key repeat, be sure to use same keycode as before in case of rotation
941 keyCode = mLocked.keyDowns.top().keyCode;
942 } else {
943 // key down
944 mLocked.keyDowns.push();
945 KeyDown& keyDown = mLocked.keyDowns.editTop();
946 keyDown.keyCode = keyCode;
947 keyDown.scanCode = scanCode;
948 }
949
950 mLocked.downTime = when;
951 } else {
952 // Remove key down.
953 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
954 if (keyDownIndex >= 0) {
955 // key up, be sure to use same keycode as before in case of rotation
956 keyCode = mLocked.keyDowns.top().keyCode;
957 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
958 } else {
959 // key was not actually down
960 LOGI("Dropping key up from device %s because the key was not down. "
961 "keyCode=%d, scanCode=%d",
962 getDeviceName().string(), keyCode, scanCode);
963 return;
964 }
Jeff Browne57e8952010-07-23 21:28:06 -0700965 }
966
Jeff Brownb51719b2010-07-29 18:18:33 -0700967 int32_t oldMetaState = mLocked.metaState;
968 newMetaState = updateMetaState(keyCode, down, oldMetaState);
969 if (oldMetaState != newMetaState) {
970 mLocked.metaState = newMetaState;
971 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700972 }
Jeff Brown8575a872010-06-30 16:10:35 -0700973
Jeff Brownb51719b2010-07-29 18:18:33 -0700974 downTime = mLocked.downTime;
975 } // release lock
976
977 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700978 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700979 }
980
Jeff Brownb51719b2010-07-29 18:18:33 -0700981 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
982}
Jeff Browne839a582010-04-22 18:58:52 -0700983
Jeff Brownb51719b2010-07-29 18:18:33 -0700984void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
985 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -0700986 int32_t policyActions = getPolicy()->interceptKey(when,
987 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700988
Jeff Browne57e8952010-07-23 21:28:06 -0700989 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Browne839a582010-04-22 18:58:52 -0700990 return; // event dropped
991 }
992
Jeff Brownb51719b2010-07-29 18:18:33 -0700993 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700994 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Browne57e8952010-07-23 21:28:06 -0700995 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700996 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Browne839a582010-04-22 18:58:52 -0700997 }
998
Jeff Browne57e8952010-07-23 21:28:06 -0700999 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brownb51719b2010-07-29 18:18:33 -07001000 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001001}
1002
Jeff Brownb51719b2010-07-29 18:18:33 -07001003ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1004 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -07001005 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001006 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07001007 return i;
1008 }
1009 }
1010 return -1;
Jeff Browne839a582010-04-22 18:58:52 -07001011}
1012
Jeff Browne57e8952010-07-23 21:28:06 -07001013int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1014 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1015}
Jeff Browne839a582010-04-22 18:58:52 -07001016
Jeff Browne57e8952010-07-23 21:28:06 -07001017int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1018 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1019}
Jeff Browne839a582010-04-22 18:58:52 -07001020
Jeff Browne57e8952010-07-23 21:28:06 -07001021bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1022 const int32_t* keyCodes, uint8_t* outFlags) {
1023 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1024}
1025
1026int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001027 { // acquire lock
1028 AutoMutex _l(mLock);
1029 return mLocked.metaState;
1030 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001031}
1032
1033
1034// --- TrackballInputMapper ---
1035
1036TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1037 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1038 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1039 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1040 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1041 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1042
Jeff Brownb51719b2010-07-29 18:18:33 -07001043 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001044}
1045
1046TrackballInputMapper::~TrackballInputMapper() {
1047}
1048
1049uint32_t TrackballInputMapper::getSources() {
1050 return AINPUT_SOURCE_TRACKBALL;
1051}
1052
1053void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1054 InputMapper::populateDeviceInfo(info);
1055
1056 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1057 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1058}
1059
Jeff Brown26c94ff2010-09-30 14:33:04 -07001060void TrackballInputMapper::dump(String8& dump) {
1061 { // acquire lock
1062 AutoMutex _l(mLock);
1063 dump.append(INDENT2 "Trackball Input Mapper:\n");
1064 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1065 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1066 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1067 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1068 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1069 } // release lock
1070}
1071
Jeff Brownb51719b2010-07-29 18:18:33 -07001072void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001073 mAccumulator.clear();
1074
Jeff Brownb51719b2010-07-29 18:18:33 -07001075 mLocked.down = false;
1076 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001077}
1078
1079void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001080 for (;;) {
1081 { // acquire lock
1082 AutoMutex _l(mLock);
1083
1084 if (! mLocked.down) {
1085 initializeLocked();
1086 break; // done
1087 }
1088 } // release lock
1089
1090 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001091 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001092 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001093 mAccumulator.btnMouse = false;
1094 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001095 }
1096
Jeff Browne57e8952010-07-23 21:28:06 -07001097 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001098}
Jeff Browne839a582010-04-22 18:58:52 -07001099
Jeff Browne57e8952010-07-23 21:28:06 -07001100void TrackballInputMapper::process(const RawEvent* rawEvent) {
1101 switch (rawEvent->type) {
1102 case EV_KEY:
1103 switch (rawEvent->scanCode) {
1104 case BTN_MOUSE:
1105 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1106 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001107 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1108 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001109 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001110 break;
Jeff Browne839a582010-04-22 18:58:52 -07001111 }
Jeff Browne57e8952010-07-23 21:28:06 -07001112 break;
Jeff Browne839a582010-04-22 18:58:52 -07001113
Jeff Browne57e8952010-07-23 21:28:06 -07001114 case EV_REL:
1115 switch (rawEvent->scanCode) {
1116 case REL_X:
1117 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1118 mAccumulator.relX = rawEvent->value;
1119 break;
1120 case REL_Y:
1121 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1122 mAccumulator.relY = rawEvent->value;
1123 break;
Jeff Browne839a582010-04-22 18:58:52 -07001124 }
Jeff Browne57e8952010-07-23 21:28:06 -07001125 break;
Jeff Browne839a582010-04-22 18:58:52 -07001126
Jeff Browne57e8952010-07-23 21:28:06 -07001127 case EV_SYN:
1128 switch (rawEvent->scanCode) {
1129 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001130 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001131 break;
Jeff Browne839a582010-04-22 18:58:52 -07001132 }
Jeff Browne57e8952010-07-23 21:28:06 -07001133 break;
Jeff Browne839a582010-04-22 18:58:52 -07001134 }
Jeff Browne839a582010-04-22 18:58:52 -07001135}
1136
Jeff Browne57e8952010-07-23 21:28:06 -07001137void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001138 uint32_t fields = mAccumulator.fields;
1139 if (fields == 0) {
1140 return; // no new state changes, so nothing to do
1141 }
1142
Jeff Brownb51719b2010-07-29 18:18:33 -07001143 int motionEventAction;
1144 PointerCoords pointerCoords;
1145 nsecs_t downTime;
1146 { // acquire lock
1147 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001148
Jeff Brownb51719b2010-07-29 18:18:33 -07001149 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1150
1151 if (downChanged) {
1152 if (mAccumulator.btnMouse) {
1153 mLocked.down = true;
1154 mLocked.downTime = when;
1155 } else {
1156 mLocked.down = false;
1157 }
Jeff Browne57e8952010-07-23 21:28:06 -07001158 }
Jeff Browne839a582010-04-22 18:58:52 -07001159
Jeff Brownb51719b2010-07-29 18:18:33 -07001160 downTime = mLocked.downTime;
1161 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1162 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001163
Jeff Brownb51719b2010-07-29 18:18:33 -07001164 if (downChanged) {
1165 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001166 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001167 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001168 }
Jeff Browne839a582010-04-22 18:58:52 -07001169
Jeff Brownb51719b2010-07-29 18:18:33 -07001170 pointerCoords.x = x;
1171 pointerCoords.y = y;
1172 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1173 pointerCoords.size = 0;
1174 pointerCoords.touchMajor = 0;
1175 pointerCoords.touchMinor = 0;
1176 pointerCoords.toolMajor = 0;
1177 pointerCoords.toolMinor = 0;
1178 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001179
Jeff Brownb51719b2010-07-29 18:18:33 -07001180 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1181 // Rotate motion based on display orientation if needed.
1182 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1183 int32_t orientation;
1184 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1185 return;
1186 }
1187
1188 float temp;
1189 switch (orientation) {
1190 case InputReaderPolicyInterface::ROTATION_90:
1191 temp = pointerCoords.x;
1192 pointerCoords.x = pointerCoords.y;
1193 pointerCoords.y = - temp;
1194 break;
1195
1196 case InputReaderPolicyInterface::ROTATION_180:
1197 pointerCoords.x = - pointerCoords.x;
1198 pointerCoords.y = - pointerCoords.y;
1199 break;
1200
1201 case InputReaderPolicyInterface::ROTATION_270:
1202 temp = pointerCoords.x;
1203 pointerCoords.x = - pointerCoords.y;
1204 pointerCoords.y = temp;
1205 break;
1206 }
1207 }
1208 } // release lock
1209
1210 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
Jeff Brownd64c8552010-08-17 20:38:35 -07001211
1212 mAccumulator.clear();
Jeff Brownb51719b2010-07-29 18:18:33 -07001213}
1214
1215void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1216 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001217 uint32_t policyFlags = 0;
1218 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1219
1220 if (! applyStandardPolicyActions(when, policyActions)) {
1221 return; // event dropped
1222 }
1223
Jeff Browne57e8952010-07-23 21:28:06 -07001224 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001225 int32_t pointerId = 0;
1226
Jeff Browne57e8952010-07-23 21:28:06 -07001227 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001228 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001229 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001230}
1231
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001232int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1233 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1234 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1235 } else {
1236 return AKEY_STATE_UNKNOWN;
1237 }
1238}
1239
Jeff Browne57e8952010-07-23 21:28:06 -07001240
1241// --- TouchInputMapper ---
1242
1243TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001244 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1245 mLocked.surfaceOrientation = -1;
1246 mLocked.surfaceWidth = -1;
1247 mLocked.surfaceHeight = -1;
1248
1249 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001250}
1251
1252TouchInputMapper::~TouchInputMapper() {
1253}
1254
1255uint32_t TouchInputMapper::getSources() {
1256 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1257}
1258
1259void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1260 InputMapper::populateDeviceInfo(info);
1261
Jeff Brownb51719b2010-07-29 18:18:33 -07001262 { // acquire lock
1263 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001264
Jeff Brownb51719b2010-07-29 18:18:33 -07001265 // Ensure surface information is up to date so that orientation changes are
1266 // noticed immediately.
1267 configureSurfaceLocked();
1268
1269 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1270 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001271
1272 if (mLocked.orientedRanges.havePressure) {
1273 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1274 mLocked.orientedRanges.pressure);
1275 }
1276
1277 if (mLocked.orientedRanges.haveSize) {
1278 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1279 mLocked.orientedRanges.size);
1280 }
1281
1282 if (mLocked.orientedRanges.haveTouchArea) {
1283 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1284 mLocked.orientedRanges.touchMajor);
1285 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1286 mLocked.orientedRanges.touchMinor);
1287 }
1288
1289 if (mLocked.orientedRanges.haveToolArea) {
1290 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1291 mLocked.orientedRanges.toolMajor);
1292 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1293 mLocked.orientedRanges.toolMinor);
1294 }
1295
1296 if (mLocked.orientedRanges.haveOrientation) {
1297 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1298 mLocked.orientedRanges.orientation);
1299 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001300 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001301}
1302
Jeff Brown26c94ff2010-09-30 14:33:04 -07001303void TouchInputMapper::dump(String8& dump) {
1304 { // acquire lock
1305 AutoMutex _l(mLock);
1306 dump.append(INDENT2 "Touch Input Mapper:\n");
1307 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1308 dumpParameters(dump);
1309 dumpVirtualKeysLocked(dump);
1310 dumpRawAxes(dump);
1311 dumpCalibration(dump);
1312 dumpSurfaceLocked(dump);
1313 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mLocked.xPrecision);
1314 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mLocked.yPrecision);
1315 } // release lock
1316}
1317
Jeff Brownb51719b2010-07-29 18:18:33 -07001318void TouchInputMapper::initializeLocked() {
1319 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001320 mLastTouch.clear();
1321 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001322
1323 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1324 mAveragingTouchFilter.historyStart[i] = 0;
1325 mAveragingTouchFilter.historyEnd[i] = 0;
1326 }
1327
1328 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001329
1330 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001331
1332 mLocked.orientedRanges.havePressure = false;
1333 mLocked.orientedRanges.haveSize = false;
1334 mLocked.orientedRanges.haveTouchArea = false;
1335 mLocked.orientedRanges.haveToolArea = false;
1336 mLocked.orientedRanges.haveOrientation = false;
1337}
1338
Jeff Browne57e8952010-07-23 21:28:06 -07001339void TouchInputMapper::configure() {
1340 InputMapper::configure();
1341
1342 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001343 configureParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001344
1345 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001346 configureRawAxes();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001347
1348 // Prepare input device calibration.
1349 parseCalibration();
1350 resolveCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001351
Jeff Brownb51719b2010-07-29 18:18:33 -07001352 { // acquire lock
1353 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001354
Jeff Brown38a7fab2010-08-30 03:02:23 -07001355 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001356 configureSurfaceLocked();
1357 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001358}
1359
Jeff Brown38a7fab2010-08-30 03:02:23 -07001360void TouchInputMapper::configureParameters() {
1361 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1362 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1363 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1364}
1365
Jeff Brown26c94ff2010-09-30 14:33:04 -07001366void TouchInputMapper::dumpParameters(String8& dump) {
1367 dump.appendFormat(INDENT3 "UseBadTouchFilter: %s\n",
1368 toString(mParameters.useBadTouchFilter));
1369 dump.appendFormat(INDENT3 "UseAveragingTouchFilter: %s\n",
1370 toString(mParameters.useAveragingTouchFilter));
1371 dump.appendFormat(INDENT3 "UseJumpyTouchFilter: %s\n",
1372 toString(mParameters.useJumpyTouchFilter));
Jeff Browna665ca82010-09-08 11:49:43 -07001373}
1374
Jeff Brown38a7fab2010-08-30 03:02:23 -07001375void TouchInputMapper::configureRawAxes() {
1376 mRawAxes.x.clear();
1377 mRawAxes.y.clear();
1378 mRawAxes.pressure.clear();
1379 mRawAxes.touchMajor.clear();
1380 mRawAxes.touchMinor.clear();
1381 mRawAxes.toolMajor.clear();
1382 mRawAxes.toolMinor.clear();
1383 mRawAxes.orientation.clear();
1384}
1385
Jeff Brown26c94ff2010-09-30 14:33:04 -07001386static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Browna665ca82010-09-08 11:49:43 -07001387 if (axis.valid) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001388 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Browna665ca82010-09-08 11:49:43 -07001389 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1390 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001391 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Browna665ca82010-09-08 11:49:43 -07001392 }
1393}
1394
Jeff Brown26c94ff2010-09-30 14:33:04 -07001395void TouchInputMapper::dumpRawAxes(String8& dump) {
1396 dump.append(INDENT3 "Raw Axes:\n");
1397 dumpAxisInfo(dump, mRawAxes.x, "X");
1398 dumpAxisInfo(dump, mRawAxes.y, "Y");
1399 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1400 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1401 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1402 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1403 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1404 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001405}
1406
Jeff Brownb51719b2010-07-29 18:18:33 -07001407bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001408 // Update orientation and dimensions if needed.
1409 int32_t orientation;
1410 int32_t width, height;
1411 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001412 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001413 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1414 return false;
1415 }
1416 } else {
1417 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001418 width = mRawAxes.x.getRange();
1419 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001420 }
1421
Jeff Brownb51719b2010-07-29 18:18:33 -07001422 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001423 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001424 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001425 }
1426
Jeff Brownb51719b2010-07-29 18:18:33 -07001427 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001428 if (sizeChanged) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001429 LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
1430 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001431
Jeff Brownb51719b2010-07-29 18:18:33 -07001432 mLocked.surfaceWidth = width;
1433 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001434
Jeff Brown38a7fab2010-08-30 03:02:23 -07001435 // Configure X and Y factors.
1436 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1437 mLocked.xOrigin = mRawAxes.x.minValue;
1438 mLocked.yOrigin = mRawAxes.y.minValue;
1439 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1440 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001441 mLocked.xPrecision = 1.0f / mLocked.xScale;
1442 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001443
Jeff Brownb51719b2010-07-29 18:18:33 -07001444 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001445 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001446 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001447 mLocked.xOrigin = 0;
1448 mLocked.yOrigin = 0;
1449 mLocked.xScale = 1.0f;
1450 mLocked.yScale = 1.0f;
1451 mLocked.xPrecision = 1.0f;
1452 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001453 }
1454
Jeff Brown38a7fab2010-08-30 03:02:23 -07001455 // Scale factor for terms that are not oriented in a particular axis.
1456 // If the pixels are square then xScale == yScale otherwise we fake it
1457 // by choosing an average.
1458 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001459
Jeff Brown38a7fab2010-08-30 03:02:23 -07001460 // Size of diagonal axis.
1461 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001462
Jeff Brown38a7fab2010-08-30 03:02:23 -07001463 // TouchMajor and TouchMinor factors.
1464 if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) {
1465 mLocked.orientedRanges.haveTouchArea = true;
1466 mLocked.orientedRanges.touchMajor.min = 0;
1467 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1468 mLocked.orientedRanges.touchMajor.flat = 0;
1469 mLocked.orientedRanges.touchMajor.fuzz = 0;
1470 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1471 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001472
Jeff Brown38a7fab2010-08-30 03:02:23 -07001473 // ToolMajor and ToolMinor factors.
1474 if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1475 mLocked.toolAreaLinearScale = 0;
1476 mLocked.toolAreaLinearBias = 0;
1477 if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) {
1478 if (mCalibration.haveToolAreaLinearScale) {
1479 mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale;
1480 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1481 mLocked.toolAreaLinearScale = float(min(width, height))
1482 / mRawAxes.toolMajor.maxValue;
1483 }
1484
1485 if (mCalibration.haveToolAreaLinearBias) {
1486 mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias;
1487 }
1488 }
1489
1490 mLocked.orientedRanges.haveToolArea = true;
1491 mLocked.orientedRanges.toolMajor.min = 0;
1492 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1493 mLocked.orientedRanges.toolMajor.flat = 0;
1494 mLocked.orientedRanges.toolMajor.fuzz = 0;
1495 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1496 }
1497
1498 // Pressure factors.
1499 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1500 RawAbsoluteAxisInfo rawPressureAxis;
1501 switch (mCalibration.pressureSource) {
1502 case Calibration::PRESSURE_SOURCE_PRESSURE:
1503 rawPressureAxis = mRawAxes.pressure;
1504 break;
1505 case Calibration::PRESSURE_SOURCE_TOUCH:
1506 rawPressureAxis = mRawAxes.touchMajor;
1507 break;
1508 default:
1509 rawPressureAxis.clear();
1510 }
1511
1512 mLocked.pressureScale = 0;
1513 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1514 || mCalibration.pressureCalibration
1515 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1516 if (mCalibration.havePressureScale) {
1517 mLocked.pressureScale = mCalibration.pressureScale;
1518 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1519 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1520 }
1521 }
1522
1523 mLocked.orientedRanges.havePressure = true;
1524 mLocked.orientedRanges.pressure.min = 0;
1525 mLocked.orientedRanges.pressure.max = 1.0;
1526 mLocked.orientedRanges.pressure.flat = 0;
1527 mLocked.orientedRanges.pressure.fuzz = 0;
1528 }
1529
1530 // Size factors.
1531 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1532 mLocked.sizeScale = 0;
1533 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1534 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1535 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1536 }
1537 }
1538
1539 mLocked.orientedRanges.haveSize = true;
1540 mLocked.orientedRanges.size.min = 0;
1541 mLocked.orientedRanges.size.max = 1.0;
1542 mLocked.orientedRanges.size.flat = 0;
1543 mLocked.orientedRanges.size.fuzz = 0;
1544 }
1545
1546 // Orientation
1547 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1548 mLocked.orientationScale = 0;
1549 if (mCalibration.orientationCalibration
1550 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1551 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1552 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1553 }
1554 }
1555
1556 mLocked.orientedRanges.orientation.min = - M_PI_2;
1557 mLocked.orientedRanges.orientation.max = M_PI_2;
1558 mLocked.orientedRanges.orientation.flat = 0;
1559 mLocked.orientedRanges.orientation.fuzz = 0;
1560 }
Jeff Browne57e8952010-07-23 21:28:06 -07001561 }
1562
1563 if (orientationChanged || sizeChanged) {
1564 // Compute oriented surface dimensions, precision, and scales.
1565 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001566 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001567 case InputReaderPolicyInterface::ROTATION_90:
1568 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001569 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1570 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1571 mLocked.orientedXPrecision = mLocked.yPrecision;
1572 mLocked.orientedYPrecision = mLocked.xPrecision;
1573 orientedXScale = mLocked.yScale;
1574 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001575 break;
1576 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001577 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1578 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1579 mLocked.orientedXPrecision = mLocked.xPrecision;
1580 mLocked.orientedYPrecision = mLocked.yPrecision;
1581 orientedXScale = mLocked.xScale;
1582 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001583 break;
1584 }
1585
1586 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001587 mLocked.orientedRanges.x.min = 0;
1588 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1589 mLocked.orientedRanges.x.flat = 0;
1590 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001591
Jeff Brownb51719b2010-07-29 18:18:33 -07001592 mLocked.orientedRanges.y.min = 0;
1593 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1594 mLocked.orientedRanges.y.flat = 0;
1595 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001596 }
1597
1598 return true;
1599}
1600
Jeff Brown26c94ff2010-09-30 14:33:04 -07001601void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1602 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1603 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1604 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Browna665ca82010-09-08 11:49:43 -07001605}
1606
Jeff Brownb51719b2010-07-29 18:18:33 -07001607void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001608 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001609
Jeff Brownb51719b2010-07-29 18:18:33 -07001610 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001611 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001612 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1613
Jeff Brownb51719b2010-07-29 18:18:33 -07001614 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001615
Jeff Brownb51719b2010-07-29 18:18:33 -07001616 if (virtualKeyDefinitions.size() == 0) {
1617 return;
1618 }
Jeff Browne57e8952010-07-23 21:28:06 -07001619
Jeff Brownb51719b2010-07-29 18:18:33 -07001620 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1621
Jeff Brown38a7fab2010-08-30 03:02:23 -07001622 int32_t touchScreenLeft = mRawAxes.x.minValue;
1623 int32_t touchScreenTop = mRawAxes.y.minValue;
1624 int32_t touchScreenWidth = mRawAxes.x.getRange();
1625 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001626
1627 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001628 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001629 virtualKeyDefinitions[i];
1630
1631 mLocked.virtualKeys.add();
1632 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1633
1634 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1635 int32_t keyCode;
1636 uint32_t flags;
1637 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1638 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001639 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1640 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001641 mLocked.virtualKeys.pop(); // drop the key
1642 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001643 }
1644
Jeff Brownb51719b2010-07-29 18:18:33 -07001645 virtualKey.keyCode = keyCode;
1646 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001647
Jeff Brownb51719b2010-07-29 18:18:33 -07001648 // convert the key definition's display coordinates into touch coordinates for a hit box
1649 int32_t halfWidth = virtualKeyDefinition.width / 2;
1650 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001651
Jeff Brownb51719b2010-07-29 18:18:33 -07001652 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1653 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1654 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1655 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1656 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1657 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1658 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1659 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001660
Jeff Brown26c94ff2010-09-30 14:33:04 -07001661 }
1662}
1663
1664void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1665 if (!mLocked.virtualKeys.isEmpty()) {
1666 dump.append(INDENT3 "Virtual Keys:\n");
1667
1668 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1669 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1670 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1671 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1672 i, virtualKey.scanCode, virtualKey.keyCode,
1673 virtualKey.hitLeft, virtualKey.hitRight,
1674 virtualKey.hitTop, virtualKey.hitBottom);
1675 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001676 }
Jeff Browne57e8952010-07-23 21:28:06 -07001677}
1678
Jeff Brown38a7fab2010-08-30 03:02:23 -07001679void TouchInputMapper::parseCalibration() {
1680 const InputDeviceCalibration& in = getDevice()->getCalibration();
1681 Calibration& out = mCalibration;
1682
1683 // Touch Area
1684 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT;
1685 String8 touchAreaCalibrationString;
1686 if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) {
1687 if (touchAreaCalibrationString == "none") {
1688 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1689 } else if (touchAreaCalibrationString == "geometric") {
1690 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC;
1691 } else if (touchAreaCalibrationString == "pressure") {
1692 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1693 } else if (touchAreaCalibrationString != "default") {
1694 LOGW("Invalid value for touch.touchArea.calibration: '%s'",
1695 touchAreaCalibrationString.string());
1696 }
1697 }
1698
1699 // Tool Area
1700 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT;
1701 String8 toolAreaCalibrationString;
1702 if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) {
1703 if (toolAreaCalibrationString == "none") {
1704 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1705 } else if (toolAreaCalibrationString == "geometric") {
1706 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC;
1707 } else if (toolAreaCalibrationString == "linear") {
1708 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1709 } else if (toolAreaCalibrationString != "default") {
1710 LOGW("Invalid value for tool.toolArea.calibration: '%s'",
1711 toolAreaCalibrationString.string());
1712 }
1713 }
1714
1715 out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"),
1716 out.toolAreaLinearScale);
1717 out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"),
1718 out.toolAreaLinearBias);
1719 out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"),
1720 out.toolAreaIsSummed);
1721
1722 // Pressure
1723 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1724 String8 pressureCalibrationString;
1725 if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) {
1726 if (pressureCalibrationString == "none") {
1727 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1728 } else if (pressureCalibrationString == "physical") {
1729 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1730 } else if (pressureCalibrationString == "amplitude") {
1731 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1732 } else if (pressureCalibrationString != "default") {
1733 LOGW("Invalid value for tool.pressure.calibration: '%s'",
1734 pressureCalibrationString.string());
1735 }
1736 }
1737
1738 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1739 String8 pressureSourceString;
1740 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1741 if (pressureSourceString == "pressure") {
1742 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1743 } else if (pressureSourceString == "touch") {
1744 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1745 } else if (pressureSourceString != "default") {
1746 LOGW("Invalid value for touch.pressure.source: '%s'",
1747 pressureSourceString.string());
1748 }
1749 }
1750
1751 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1752 out.pressureScale);
1753
1754 // Size
1755 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1756 String8 sizeCalibrationString;
1757 if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) {
1758 if (sizeCalibrationString == "none") {
1759 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1760 } else if (sizeCalibrationString == "normalized") {
1761 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1762 } else if (sizeCalibrationString != "default") {
1763 LOGW("Invalid value for tool.size.calibration: '%s'",
1764 sizeCalibrationString.string());
1765 }
1766 }
1767
1768 // Orientation
1769 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1770 String8 orientationCalibrationString;
1771 if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) {
1772 if (orientationCalibrationString == "none") {
1773 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1774 } else if (orientationCalibrationString == "interpolated") {
1775 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1776 } else if (orientationCalibrationString != "default") {
1777 LOGW("Invalid value for tool.orientation.calibration: '%s'",
1778 orientationCalibrationString.string());
1779 }
1780 }
1781}
1782
1783void TouchInputMapper::resolveCalibration() {
1784 // Pressure
1785 switch (mCalibration.pressureSource) {
1786 case Calibration::PRESSURE_SOURCE_DEFAULT:
1787 if (mRawAxes.pressure.valid) {
1788 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1789 } else if (mRawAxes.touchMajor.valid) {
1790 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1791 }
1792 break;
1793
1794 case Calibration::PRESSURE_SOURCE_PRESSURE:
1795 if (! mRawAxes.pressure.valid) {
1796 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1797 "the pressure axis is not available.");
1798 }
1799 break;
1800
1801 case Calibration::PRESSURE_SOURCE_TOUCH:
1802 if (! mRawAxes.touchMajor.valid) {
1803 LOGW("Calibration property touch.pressure.source is 'touch' but "
1804 "the touchMajor axis is not available.");
1805 }
1806 break;
1807
1808 default:
1809 break;
1810 }
1811
1812 switch (mCalibration.pressureCalibration) {
1813 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1814 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1815 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1816 } else {
1817 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1818 }
1819 break;
1820
1821 default:
1822 break;
1823 }
1824
1825 // Tool Area
1826 switch (mCalibration.toolAreaCalibration) {
1827 case Calibration::TOOL_AREA_CALIBRATION_DEFAULT:
1828 if (mRawAxes.toolMajor.valid) {
1829 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1830 } else {
1831 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1832 }
1833 break;
1834
1835 default:
1836 break;
1837 }
1838
1839 // Touch Area
1840 switch (mCalibration.touchAreaCalibration) {
1841 case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT:
1842 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
1843 && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1844 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1845 } else {
1846 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1847 }
1848 break;
1849
1850 default:
1851 break;
1852 }
1853
1854 // Size
1855 switch (mCalibration.sizeCalibration) {
1856 case Calibration::SIZE_CALIBRATION_DEFAULT:
1857 if (mRawAxes.toolMajor.valid) {
1858 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1859 } else {
1860 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1861 }
1862 break;
1863
1864 default:
1865 break;
1866 }
1867
1868 // Orientation
1869 switch (mCalibration.orientationCalibration) {
1870 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1871 if (mRawAxes.orientation.valid) {
1872 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1873 } else {
1874 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1875 }
1876 break;
1877
1878 default:
1879 break;
1880 }
1881}
1882
Jeff Brown26c94ff2010-09-30 14:33:04 -07001883void TouchInputMapper::dumpCalibration(String8& dump) {
1884 dump.append(INDENT3 "Calibration:\n");
Jeff Browna665ca82010-09-08 11:49:43 -07001885
Jeff Brown38a7fab2010-08-30 03:02:23 -07001886 // Touch Area
1887 switch (mCalibration.touchAreaCalibration) {
1888 case Calibration::TOUCH_AREA_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001889 dump.append(INDENT4 "touch.touchArea.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001890 break;
1891 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001892 dump.append(INDENT4 "touch.touchArea.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001893 break;
1894 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001895 dump.append(INDENT4 "touch.touchArea.calibration: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001896 break;
1897 default:
1898 assert(false);
1899 }
1900
1901 // Tool Area
1902 switch (mCalibration.toolAreaCalibration) {
1903 case Calibration::TOOL_AREA_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001904 dump.append(INDENT4 "touch.toolArea.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001905 break;
1906 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001907 dump.append(INDENT4 "touch.toolArea.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001908 break;
1909 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001910 dump.append(INDENT4 "touch.toolArea.calibration: linear\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001911 break;
1912 default:
1913 assert(false);
1914 }
1915
1916 if (mCalibration.haveToolAreaLinearScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001917 dump.appendFormat(INDENT4 "touch.toolArea.linearScale: %0.3f\n",
1918 mCalibration.toolAreaLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001919 }
1920
1921 if (mCalibration.haveToolAreaLinearBias) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001922 dump.appendFormat(INDENT4 "touch.toolArea.linearBias: %0.3f\n",
1923 mCalibration.toolAreaLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001924 }
1925
1926 if (mCalibration.haveToolAreaIsSummed) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001927 dump.appendFormat(INDENT4 "touch.toolArea.isSummed: %d\n",
1928 mCalibration.toolAreaIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001929 }
1930
1931 // Pressure
1932 switch (mCalibration.pressureCalibration) {
1933 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001934 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001935 break;
1936 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001937 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001938 break;
1939 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001940 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001941 break;
1942 default:
1943 assert(false);
1944 }
1945
1946 switch (mCalibration.pressureSource) {
1947 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001948 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001949 break;
1950 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001951 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001952 break;
1953 case Calibration::PRESSURE_SOURCE_DEFAULT:
1954 break;
1955 default:
1956 assert(false);
1957 }
1958
1959 if (mCalibration.havePressureScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001960 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
1961 mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001962 }
1963
1964 // Size
1965 switch (mCalibration.sizeCalibration) {
1966 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001967 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001968 break;
1969 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001970 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001971 break;
1972 default:
1973 assert(false);
1974 }
1975
1976 // Orientation
1977 switch (mCalibration.orientationCalibration) {
1978 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001979 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001980 break;
1981 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001982 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001983 break;
1984 default:
1985 assert(false);
1986 }
1987}
1988
Jeff Browne57e8952010-07-23 21:28:06 -07001989void TouchInputMapper::reset() {
1990 // Synthesize touch up event if touch is currently down.
1991 // This will also take care of finishing virtual key processing if needed.
1992 if (mLastTouch.pointerCount != 0) {
1993 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1994 mCurrentTouch.clear();
1995 syncTouch(when, true);
1996 }
1997
Jeff Brownb51719b2010-07-29 18:18:33 -07001998 { // acquire lock
1999 AutoMutex _l(mLock);
2000 initializeLocked();
2001 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002002
Jeff Brownb51719b2010-07-29 18:18:33 -07002003 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07002004}
2005
2006void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002007 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07002008
2009 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07002010 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
2011
2012 if (! applyStandardPolicyActions(when, policyActions)) {
2013 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07002014 return; // event dropped
2015 }
2016
Jeff Brownb51719b2010-07-29 18:18:33 -07002017 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07002018
Jeff Browne57e8952010-07-23 21:28:06 -07002019 if (mParameters.useBadTouchFilter) {
2020 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002021 havePointerIds = false;
2022 }
2023 }
2024
Jeff Browne57e8952010-07-23 21:28:06 -07002025 if (mParameters.useJumpyTouchFilter) {
2026 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002027 havePointerIds = false;
2028 }
2029 }
2030
2031 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002032 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002033 }
2034
Jeff Browne57e8952010-07-23 21:28:06 -07002035 TouchData temp;
2036 TouchData* savedTouch;
2037 if (mParameters.useAveragingTouchFilter) {
2038 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002039 savedTouch = & temp;
2040
Jeff Browne57e8952010-07-23 21:28:06 -07002041 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002042 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002043 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002044 }
2045
Jeff Brownb51719b2010-07-29 18:18:33 -07002046 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002047
Jeff Browne57e8952010-07-23 21:28:06 -07002048 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2049 if (touchResult == DISPATCH_TOUCH) {
2050 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002051 }
2052
Jeff Brownb51719b2010-07-29 18:18:33 -07002053 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002054
Jeff Browne57e8952010-07-23 21:28:06 -07002055 if (touchResult == DROP_STROKE) {
2056 mLastTouch.clear();
2057 } else {
2058 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002059 }
Jeff Browne839a582010-04-22 18:58:52 -07002060}
2061
Jeff Browne57e8952010-07-23 21:28:06 -07002062TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2063 nsecs_t when, uint32_t policyFlags) {
2064 int32_t keyEventAction, keyEventFlags;
2065 int32_t keyCode, scanCode, downTime;
2066 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002067
Jeff Brownb51719b2010-07-29 18:18:33 -07002068 { // acquire lock
2069 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002070
Jeff Brownb51719b2010-07-29 18:18:33 -07002071 // Update surface size and orientation, including virtual key positions.
2072 if (! configureSurfaceLocked()) {
2073 return DROP_STROKE;
2074 }
2075
2076 // Check for virtual key press.
2077 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002078 if (mCurrentTouch.pointerCount == 0) {
2079 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002080 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002081#if DEBUG_VIRTUAL_KEYS
2082 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2083 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2084#endif
2085 keyEventAction = AKEY_EVENT_ACTION_UP;
2086 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2087 touchResult = SKIP_TOUCH;
2088 goto DispatchVirtualKey;
2089 }
2090
2091 if (mCurrentTouch.pointerCount == 1) {
2092 int32_t x = mCurrentTouch.pointers[0].x;
2093 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002094 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2095 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002096 // Pointer is still within the space of the virtual key.
2097 return SKIP_TOUCH;
2098 }
2099 }
2100
2101 // Pointer left virtual key area or another pointer also went down.
2102 // Send key cancellation and drop the stroke so subsequent motions will be
2103 // considered fresh downs. This is useful when the user swipes away from the
2104 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002105 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002106#if DEBUG_VIRTUAL_KEYS
2107 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2108 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2109#endif
2110 keyEventAction = AKEY_EVENT_ACTION_UP;
2111 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2112 | AKEY_EVENT_FLAG_CANCELED;
2113 touchResult = DROP_STROKE;
2114 goto DispatchVirtualKey;
2115 } else {
2116 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2117 // Pointer just went down. Handle off-screen touches, if needed.
2118 int32_t x = mCurrentTouch.pointers[0].x;
2119 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002120 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002121 // If exactly one pointer went down, check for virtual key hit.
2122 // Otherwise we will drop the entire stroke.
2123 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002124 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002125 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002126 mLocked.currentVirtualKey.down = true;
2127 mLocked.currentVirtualKey.downTime = when;
2128 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2129 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002130#if DEBUG_VIRTUAL_KEYS
2131 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2132 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2133#endif
2134 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2135 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2136 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2137 touchResult = SKIP_TOUCH;
2138 goto DispatchVirtualKey;
2139 }
2140 }
2141 return DROP_STROKE;
2142 }
2143 }
2144 return DISPATCH_TOUCH;
2145 }
2146
2147 DispatchVirtualKey:
2148 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002149 keyCode = mLocked.currentVirtualKey.keyCode;
2150 scanCode = mLocked.currentVirtualKey.scanCode;
2151 downTime = mLocked.currentVirtualKey.downTime;
2152 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002153
2154 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002155 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
2156 keyCode, scanCode, downTime);
2157 return touchResult;
2158}
2159
2160void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
2161 int32_t keyEventAction, int32_t keyEventFlags,
2162 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07002163 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07002164
Jeff Brown5c1ed842010-07-14 18:48:53 -07002165 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Browne57e8952010-07-23 21:28:06 -07002166 getPolicy()->virtualKeyDownFeedback();
Jeff Brownf16c26d2010-07-02 15:37:36 -07002167 }
Jeff Browne839a582010-04-22 18:58:52 -07002168
Jeff Browne57e8952010-07-23 21:28:06 -07002169 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002170 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07002171
Jeff Browne57e8952010-07-23 21:28:06 -07002172 if (applyStandardPolicyActions(when, policyActions)) {
2173 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07002174 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2175 }
Jeff Browne839a582010-04-22 18:58:52 -07002176}
2177
Jeff Browne57e8952010-07-23 21:28:06 -07002178void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2179 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2180 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002181 if (currentPointerCount == 0 && lastPointerCount == 0) {
2182 return; // nothing to do!
2183 }
2184
Jeff Browne57e8952010-07-23 21:28:06 -07002185 BitSet32 currentIdBits = mCurrentTouch.idBits;
2186 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002187
2188 if (currentIdBits == lastIdBits) {
2189 // No pointer id changes so this is a move event.
2190 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002191 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002192 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002193 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002194 } else {
2195 // There may be pointers going up and pointers going down at the same time when pointer
2196 // ids are reported by the device driver.
2197 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2198 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2199 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002200 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002201
2202 while (! upIdBits.isEmpty()) {
2203 uint32_t upId = upIdBits.firstMarkedBit();
2204 upIdBits.clearBit(upId);
2205 BitSet32 oldActiveIdBits = activeIdBits;
2206 activeIdBits.clearBit(upId);
2207
2208 int32_t motionEventAction;
2209 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002210 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002211 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002212 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002213 }
2214
Jeff Browne57e8952010-07-23 21:28:06 -07002215 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002216 oldActiveIdBits, upId, pointerCount, motionEventAction);
2217 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002218 }
2219
2220 while (! downIdBits.isEmpty()) {
2221 uint32_t downId = downIdBits.firstMarkedBit();
2222 downIdBits.clearBit(downId);
2223 BitSet32 oldActiveIdBits = activeIdBits;
2224 activeIdBits.markBit(downId);
2225
2226 int32_t motionEventAction;
2227 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002228 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002229 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002230 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002231 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002232 }
2233
Jeff Brown38a7fab2010-08-30 03:02:23 -07002234 pointerCount += 1;
Jeff Browne57e8952010-07-23 21:28:06 -07002235 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002236 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002237 }
2238 }
2239}
2240
Jeff Browne57e8952010-07-23 21:28:06 -07002241void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002242 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002243 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002244 int32_t pointerIds[MAX_POINTERS];
2245 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002246 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002247 float xPrecision, yPrecision;
2248
2249 { // acquire lock
2250 AutoMutex _l(mLock);
2251
2252 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2253 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002254 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002255 uint32_t id = idBits.firstMarkedBit();
2256 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002257 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002258
Jeff Brown38a7fab2010-08-30 03:02:23 -07002259 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002260
Jeff Brown38a7fab2010-08-30 03:02:23 -07002261 // X and Y
2262 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2263 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002264
Jeff Brown38a7fab2010-08-30 03:02:23 -07002265 // ToolMajor and ToolMinor
2266 float toolMajor, toolMinor;
2267 switch (mCalibration.toolAreaCalibration) {
2268 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
2269 toolMajor = in.toolMajor * mLocked.geometricScale;
2270 if (mRawAxes.toolMinor.valid) {
2271 toolMinor = in.toolMinor * mLocked.geometricScale;
2272 } else {
2273 toolMinor = toolMajor;
2274 }
2275 break;
2276 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
2277 toolMajor = in.toolMajor != 0
2278 ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias
2279 : 0;
2280 if (mRawAxes.toolMinor.valid) {
2281 toolMinor = in.toolMinor != 0
2282 ? in.toolMinor * mLocked.toolAreaLinearScale
2283 + mLocked.toolAreaLinearBias
2284 : 0;
2285 } else {
2286 toolMinor = toolMajor;
2287 }
2288 break;
2289 default:
2290 toolMajor = 0;
2291 toolMinor = 0;
2292 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002293 }
2294
Jeff Brown38a7fab2010-08-30 03:02:23 -07002295 if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) {
2296 toolMajor /= pointerCount;
2297 toolMinor /= pointerCount;
2298 }
2299
2300 // Pressure
2301 float rawPressure;
2302 switch (mCalibration.pressureSource) {
2303 case Calibration::PRESSURE_SOURCE_PRESSURE:
2304 rawPressure = in.pressure;
2305 break;
2306 case Calibration::PRESSURE_SOURCE_TOUCH:
2307 rawPressure = in.touchMajor;
2308 break;
2309 default:
2310 rawPressure = 0;
2311 }
2312
2313 float pressure;
2314 switch (mCalibration.pressureCalibration) {
2315 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2316 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2317 pressure = rawPressure * mLocked.pressureScale;
2318 break;
2319 default:
2320 pressure = 1;
2321 break;
2322 }
2323
2324 // TouchMajor and TouchMinor
2325 float touchMajor, touchMinor;
2326 switch (mCalibration.touchAreaCalibration) {
2327 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
2328 touchMajor = in.touchMajor * mLocked.geometricScale;
2329 if (mRawAxes.touchMinor.valid) {
2330 touchMinor = in.touchMinor * mLocked.geometricScale;
2331 } else {
2332 touchMinor = touchMajor;
2333 }
2334 break;
2335 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
2336 touchMajor = toolMajor * pressure;
2337 touchMinor = toolMinor * pressure;
2338 break;
2339 default:
2340 touchMajor = 0;
2341 touchMinor = 0;
2342 break;
2343 }
2344
2345 if (touchMajor > toolMajor) {
2346 touchMajor = toolMajor;
2347 }
2348 if (touchMinor > toolMinor) {
2349 touchMinor = toolMinor;
2350 }
2351
2352 // Size
2353 float size;
2354 switch (mCalibration.sizeCalibration) {
2355 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2356 float rawSize = mRawAxes.toolMinor.valid
2357 ? avg(in.toolMajor, in.toolMinor)
2358 : in.toolMajor;
2359 size = rawSize * mLocked.sizeScale;
2360 break;
2361 }
2362 default:
2363 size = 0;
2364 break;
2365 }
2366
2367 // Orientation
2368 float orientation;
2369 switch (mCalibration.orientationCalibration) {
2370 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2371 orientation = in.orientation * mLocked.orientationScale;
2372 break;
2373 default:
2374 orientation = 0;
2375 }
2376
2377 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002378 switch (mLocked.surfaceOrientation) {
2379 case InputReaderPolicyInterface::ROTATION_90: {
2380 float xTemp = x;
2381 x = y;
2382 y = mLocked.surfaceWidth - xTemp;
2383 orientation -= M_PI_2;
2384 if (orientation < - M_PI_2) {
2385 orientation += M_PI;
2386 }
2387 break;
2388 }
2389 case InputReaderPolicyInterface::ROTATION_180: {
2390 x = mLocked.surfaceWidth - x;
2391 y = mLocked.surfaceHeight - y;
2392 orientation = - orientation;
2393 break;
2394 }
2395 case InputReaderPolicyInterface::ROTATION_270: {
2396 float xTemp = x;
2397 x = mLocked.surfaceHeight - y;
2398 y = xTemp;
2399 orientation += M_PI_2;
2400 if (orientation > M_PI_2) {
2401 orientation -= M_PI;
2402 }
2403 break;
2404 }
2405 }
2406
Jeff Brown38a7fab2010-08-30 03:02:23 -07002407 // Write output coords.
2408 PointerCoords& out = pointerCoords[outIndex];
2409 out.x = x;
2410 out.y = y;
2411 out.pressure = pressure;
2412 out.size = size;
2413 out.touchMajor = touchMajor;
2414 out.touchMinor = touchMinor;
2415 out.toolMajor = toolMajor;
2416 out.toolMinor = toolMinor;
2417 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002418
Jeff Brown38a7fab2010-08-30 03:02:23 -07002419 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002420
2421 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002422 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002423 }
Jeff Browne839a582010-04-22 18:58:52 -07002424 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002425
2426 // Check edge flags by looking only at the first pointer since the flags are
2427 // global to the event.
2428 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2429 if (pointerCoords[0].x <= 0) {
2430 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2431 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2432 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2433 }
2434 if (pointerCoords[0].y <= 0) {
2435 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2436 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2437 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2438 }
Jeff Browne839a582010-04-22 18:58:52 -07002439 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002440
2441 xPrecision = mLocked.orientedXPrecision;
2442 yPrecision = mLocked.orientedYPrecision;
2443 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002444
Jeff Browne57e8952010-07-23 21:28:06 -07002445 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002446 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002447 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002448 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002449}
2450
Jeff Brownb51719b2010-07-29 18:18:33 -07002451bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002452 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2453 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2454 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002455 }
Jeff Browne57e8952010-07-23 21:28:06 -07002456 return true;
2457}
2458
Jeff Brownb51719b2010-07-29 18:18:33 -07002459const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2460 int32_t x, int32_t y) {
2461 size_t numVirtualKeys = mLocked.virtualKeys.size();
2462 for (size_t i = 0; i < numVirtualKeys; i++) {
2463 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002464
2465#if DEBUG_VIRTUAL_KEYS
2466 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2467 "left=%d, top=%d, right=%d, bottom=%d",
2468 x, y,
2469 virtualKey.keyCode, virtualKey.scanCode,
2470 virtualKey.hitLeft, virtualKey.hitTop,
2471 virtualKey.hitRight, virtualKey.hitBottom);
2472#endif
2473
2474 if (virtualKey.isHit(x, y)) {
2475 return & virtualKey;
2476 }
2477 }
2478
2479 return NULL;
2480}
2481
2482void TouchInputMapper::calculatePointerIds() {
2483 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2484 uint32_t lastPointerCount = mLastTouch.pointerCount;
2485
2486 if (currentPointerCount == 0) {
2487 // No pointers to assign.
2488 mCurrentTouch.idBits.clear();
2489 } else if (lastPointerCount == 0) {
2490 // All pointers are new.
2491 mCurrentTouch.idBits.clear();
2492 for (uint32_t i = 0; i < currentPointerCount; i++) {
2493 mCurrentTouch.pointers[i].id = i;
2494 mCurrentTouch.idToIndex[i] = i;
2495 mCurrentTouch.idBits.markBit(i);
2496 }
2497 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2498 // Only one pointer and no change in count so it must have the same id as before.
2499 uint32_t id = mLastTouch.pointers[0].id;
2500 mCurrentTouch.pointers[0].id = id;
2501 mCurrentTouch.idToIndex[id] = 0;
2502 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2503 } else {
2504 // General case.
2505 // We build a heap of squared euclidean distances between current and last pointers
2506 // associated with the current and last pointer indices. Then, we find the best
2507 // match (by distance) for each current pointer.
2508 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2509
2510 uint32_t heapSize = 0;
2511 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2512 currentPointerIndex++) {
2513 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2514 lastPointerIndex++) {
2515 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2516 - mLastTouch.pointers[lastPointerIndex].x;
2517 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2518 - mLastTouch.pointers[lastPointerIndex].y;
2519
2520 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2521
2522 // Insert new element into the heap (sift up).
2523 heap[heapSize].currentPointerIndex = currentPointerIndex;
2524 heap[heapSize].lastPointerIndex = lastPointerIndex;
2525 heap[heapSize].distance = distance;
2526 heapSize += 1;
2527 }
2528 }
2529
2530 // Heapify
2531 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2532 startIndex -= 1;
2533 for (uint32_t parentIndex = startIndex; ;) {
2534 uint32_t childIndex = parentIndex * 2 + 1;
2535 if (childIndex >= heapSize) {
2536 break;
2537 }
2538
2539 if (childIndex + 1 < heapSize
2540 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2541 childIndex += 1;
2542 }
2543
2544 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2545 break;
2546 }
2547
2548 swap(heap[parentIndex], heap[childIndex]);
2549 parentIndex = childIndex;
2550 }
2551 }
2552
2553#if DEBUG_POINTER_ASSIGNMENT
2554 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2555 for (size_t i = 0; i < heapSize; i++) {
2556 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2557 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2558 heap[i].distance);
2559 }
2560#endif
2561
2562 // Pull matches out by increasing order of distance.
2563 // To avoid reassigning pointers that have already been matched, the loop keeps track
2564 // of which last and current pointers have been matched using the matchedXXXBits variables.
2565 // It also tracks the used pointer id bits.
2566 BitSet32 matchedLastBits(0);
2567 BitSet32 matchedCurrentBits(0);
2568 BitSet32 usedIdBits(0);
2569 bool first = true;
2570 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2571 for (;;) {
2572 if (first) {
2573 // The first time through the loop, we just consume the root element of
2574 // the heap (the one with smallest distance).
2575 first = false;
2576 } else {
2577 // Previous iterations consumed the root element of the heap.
2578 // Pop root element off of the heap (sift down).
2579 heapSize -= 1;
2580 assert(heapSize > 0);
2581
2582 // Sift down.
2583 heap[0] = heap[heapSize];
2584 for (uint32_t parentIndex = 0; ;) {
2585 uint32_t childIndex = parentIndex * 2 + 1;
2586 if (childIndex >= heapSize) {
2587 break;
2588 }
2589
2590 if (childIndex + 1 < heapSize
2591 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2592 childIndex += 1;
2593 }
2594
2595 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2596 break;
2597 }
2598
2599 swap(heap[parentIndex], heap[childIndex]);
2600 parentIndex = childIndex;
2601 }
2602
2603#if DEBUG_POINTER_ASSIGNMENT
2604 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2605 for (size_t i = 0; i < heapSize; i++) {
2606 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2607 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2608 heap[i].distance);
2609 }
2610#endif
2611 }
2612
2613 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2614 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2615
2616 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2617 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2618
2619 matchedCurrentBits.markBit(currentPointerIndex);
2620 matchedLastBits.markBit(lastPointerIndex);
2621
2622 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2623 mCurrentTouch.pointers[currentPointerIndex].id = id;
2624 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2625 usedIdBits.markBit(id);
2626
2627#if DEBUG_POINTER_ASSIGNMENT
2628 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2629 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2630#endif
2631 break;
2632 }
2633 }
2634
2635 // Assign fresh ids to new pointers.
2636 if (currentPointerCount > lastPointerCount) {
2637 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2638 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2639 uint32_t id = usedIdBits.firstUnmarkedBit();
2640
2641 mCurrentTouch.pointers[currentPointerIndex].id = id;
2642 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2643 usedIdBits.markBit(id);
2644
2645#if DEBUG_POINTER_ASSIGNMENT
2646 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2647 currentPointerIndex, id);
2648#endif
2649
2650 if (--i == 0) break; // done
2651 matchedCurrentBits.markBit(currentPointerIndex);
2652 }
2653 }
2654
2655 // Fix id bits.
2656 mCurrentTouch.idBits = usedIdBits;
2657 }
2658}
2659
2660/* Special hack for devices that have bad screen data: if one of the
2661 * points has moved more than a screen height from the last position,
2662 * then drop it. */
2663bool TouchInputMapper::applyBadTouchFilter() {
2664 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002665 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002666 return false;
2667 }
2668
2669 uint32_t pointerCount = mCurrentTouch.pointerCount;
2670
2671 // Nothing to do if there are no points.
2672 if (pointerCount == 0) {
2673 return false;
2674 }
2675
2676 // Don't do anything if a finger is going down or up. We run
2677 // here before assigning pointer IDs, so there isn't a good
2678 // way to do per-finger matching.
2679 if (pointerCount != mLastTouch.pointerCount) {
2680 return false;
2681 }
2682
2683 // We consider a single movement across more than a 7/16 of
2684 // the long size of the screen to be bad. This was a magic value
2685 // determined by looking at the maximum distance it is feasible
2686 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002687 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002688
2689 // XXX The original code in InputDevice.java included commented out
2690 // code for testing the X axis. Note that when we drop a point
2691 // we don't actually restore the old X either. Strange.
2692 // The old code also tries to track when bad points were previously
2693 // detected but it turns out that due to the placement of a "break"
2694 // at the end of the loop, we never set mDroppedBadPoint to true
2695 // so it is effectively dead code.
2696 // Need to figure out if the old code is busted or just overcomplicated
2697 // but working as intended.
2698
2699 // Look through all new points and see if any are farther than
2700 // acceptable from all previous points.
2701 for (uint32_t i = pointerCount; i-- > 0; ) {
2702 int32_t y = mCurrentTouch.pointers[i].y;
2703 int32_t closestY = INT_MAX;
2704 int32_t closestDeltaY = 0;
2705
2706#if DEBUG_HACKS
2707 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2708#endif
2709
2710 for (uint32_t j = pointerCount; j-- > 0; ) {
2711 int32_t lastY = mLastTouch.pointers[j].y;
2712 int32_t deltaY = abs(y - lastY);
2713
2714#if DEBUG_HACKS
2715 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2716 j, lastY, deltaY);
2717#endif
2718
2719 if (deltaY < maxDeltaY) {
2720 goto SkipSufficientlyClosePoint;
2721 }
2722 if (deltaY < closestDeltaY) {
2723 closestDeltaY = deltaY;
2724 closestY = lastY;
2725 }
2726 }
2727
2728 // Must not have found a close enough match.
2729#if DEBUG_HACKS
2730 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2731 i, y, closestY, closestDeltaY, maxDeltaY);
2732#endif
2733
2734 mCurrentTouch.pointers[i].y = closestY;
2735 return true; // XXX original code only corrects one point
2736
2737 SkipSufficientlyClosePoint: ;
2738 }
2739
2740 // No change.
2741 return false;
2742}
2743
2744/* Special hack for devices that have bad screen data: drop points where
2745 * the coordinate value for one axis has jumped to the other pointer's location.
2746 */
2747bool TouchInputMapper::applyJumpyTouchFilter() {
2748 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002749 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002750 return false;
2751 }
2752
2753 uint32_t pointerCount = mCurrentTouch.pointerCount;
2754 if (mLastTouch.pointerCount != pointerCount) {
2755#if DEBUG_HACKS
2756 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2757 mLastTouch.pointerCount, pointerCount);
2758 for (uint32_t i = 0; i < pointerCount; i++) {
2759 LOGD(" Pointer %d (%d, %d)", i,
2760 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2761 }
2762#endif
2763
2764 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2765 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2766 // Just drop the first few events going from 1 to 2 pointers.
2767 // They're bad often enough that they're not worth considering.
2768 mCurrentTouch.pointerCount = 1;
2769 mJumpyTouchFilter.jumpyPointsDropped += 1;
2770
2771#if DEBUG_HACKS
2772 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2773#endif
2774 return true;
2775 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2776 // The event when we go from 2 -> 1 tends to be messed up too
2777 mCurrentTouch.pointerCount = 2;
2778 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2779 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2780 mJumpyTouchFilter.jumpyPointsDropped += 1;
2781
2782#if DEBUG_HACKS
2783 for (int32_t i = 0; i < 2; i++) {
2784 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2785 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2786 }
2787#endif
2788 return true;
2789 }
2790 }
2791 // Reset jumpy points dropped on other transitions or if limit exceeded.
2792 mJumpyTouchFilter.jumpyPointsDropped = 0;
2793
2794#if DEBUG_HACKS
2795 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2796#endif
2797 return false;
2798 }
2799
2800 // We have the same number of pointers as last time.
2801 // A 'jumpy' point is one where the coordinate value for one axis
2802 // has jumped to the other pointer's location. No need to do anything
2803 // else if we only have one pointer.
2804 if (pointerCount < 2) {
2805 return false;
2806 }
2807
2808 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002809 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002810
2811 // We only replace the single worst jumpy point as characterized by pointer distance
2812 // in a single axis.
2813 int32_t badPointerIndex = -1;
2814 int32_t badPointerReplacementIndex = -1;
2815 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2816
2817 for (uint32_t i = pointerCount; i-- > 0; ) {
2818 int32_t x = mCurrentTouch.pointers[i].x;
2819 int32_t y = mCurrentTouch.pointers[i].y;
2820
2821#if DEBUG_HACKS
2822 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2823#endif
2824
2825 // Check if a touch point is too close to another's coordinates
2826 bool dropX = false, dropY = false;
2827 for (uint32_t j = 0; j < pointerCount; j++) {
2828 if (i == j) {
2829 continue;
2830 }
2831
2832 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2833 dropX = true;
2834 break;
2835 }
2836
2837 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2838 dropY = true;
2839 break;
2840 }
2841 }
2842 if (! dropX && ! dropY) {
2843 continue; // not jumpy
2844 }
2845
2846 // Find a replacement candidate by comparing with older points on the
2847 // complementary (non-jumpy) axis.
2848 int32_t distance = INT_MIN; // distance to be corrected
2849 int32_t replacementIndex = -1;
2850
2851 if (dropX) {
2852 // X looks too close. Find an older replacement point with a close Y.
2853 int32_t smallestDeltaY = INT_MAX;
2854 for (uint32_t j = 0; j < pointerCount; j++) {
2855 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2856 if (deltaY < smallestDeltaY) {
2857 smallestDeltaY = deltaY;
2858 replacementIndex = j;
2859 }
2860 }
2861 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2862 } else {
2863 // Y looks too close. Find an older replacement point with a close X.
2864 int32_t smallestDeltaX = INT_MAX;
2865 for (uint32_t j = 0; j < pointerCount; j++) {
2866 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2867 if (deltaX < smallestDeltaX) {
2868 smallestDeltaX = deltaX;
2869 replacementIndex = j;
2870 }
2871 }
2872 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2873 }
2874
2875 // If replacing this pointer would correct a worse error than the previous ones
2876 // considered, then use this replacement instead.
2877 if (distance > badPointerDistance) {
2878 badPointerIndex = i;
2879 badPointerReplacementIndex = replacementIndex;
2880 badPointerDistance = distance;
2881 }
2882 }
2883
2884 // Correct the jumpy pointer if one was found.
2885 if (badPointerIndex >= 0) {
2886#if DEBUG_HACKS
2887 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2888 badPointerIndex,
2889 mLastTouch.pointers[badPointerReplacementIndex].x,
2890 mLastTouch.pointers[badPointerReplacementIndex].y);
2891#endif
2892
2893 mCurrentTouch.pointers[badPointerIndex].x =
2894 mLastTouch.pointers[badPointerReplacementIndex].x;
2895 mCurrentTouch.pointers[badPointerIndex].y =
2896 mLastTouch.pointers[badPointerReplacementIndex].y;
2897 mJumpyTouchFilter.jumpyPointsDropped += 1;
2898 return true;
2899 }
2900 }
2901
2902 mJumpyTouchFilter.jumpyPointsDropped = 0;
2903 return false;
2904}
2905
2906/* Special hack for devices that have bad screen data: aggregate and
2907 * compute averages of the coordinate data, to reduce the amount of
2908 * jitter seen by applications. */
2909void TouchInputMapper::applyAveragingTouchFilter() {
2910 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2911 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2912 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2913 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002914 int32_t pressure;
2915 switch (mCalibration.pressureSource) {
2916 case Calibration::PRESSURE_SOURCE_PRESSURE:
2917 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2918 break;
2919 case Calibration::PRESSURE_SOURCE_TOUCH:
2920 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2921 break;
2922 default:
2923 pressure = 1;
2924 break;
2925 }
Jeff Browne57e8952010-07-23 21:28:06 -07002926
2927 if (mLastTouch.idBits.hasBit(id)) {
2928 // Pointer was down before and is still down now.
2929 // Compute average over history trace.
2930 uint32_t start = mAveragingTouchFilter.historyStart[id];
2931 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2932
2933 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2934 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2935 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2936
2937#if DEBUG_HACKS
2938 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2939 id, distance);
2940#endif
2941
2942 if (distance < AVERAGING_DISTANCE_LIMIT) {
2943 // Increment end index in preparation for recording new historical data.
2944 end += 1;
2945 if (end > AVERAGING_HISTORY_SIZE) {
2946 end = 0;
2947 }
2948
2949 // If the end index has looped back to the start index then we have filled
2950 // the historical trace up to the desired size so we drop the historical
2951 // data at the start of the trace.
2952 if (end == start) {
2953 start += 1;
2954 if (start > AVERAGING_HISTORY_SIZE) {
2955 start = 0;
2956 }
2957 }
2958
2959 // Add the raw data to the historical trace.
2960 mAveragingTouchFilter.historyStart[id] = start;
2961 mAveragingTouchFilter.historyEnd[id] = end;
2962 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2963 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2964 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2965
2966 // Average over all historical positions in the trace by total pressure.
2967 int32_t averagedX = 0;
2968 int32_t averagedY = 0;
2969 int32_t totalPressure = 0;
2970 for (;;) {
2971 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2972 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2973 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2974 .pointers[id].pressure;
2975
2976 averagedX += historicalX * historicalPressure;
2977 averagedY += historicalY * historicalPressure;
2978 totalPressure += historicalPressure;
2979
2980 if (start == end) {
2981 break;
2982 }
2983
2984 start += 1;
2985 if (start > AVERAGING_HISTORY_SIZE) {
2986 start = 0;
2987 }
2988 }
2989
Jeff Brown38a7fab2010-08-30 03:02:23 -07002990 if (totalPressure != 0) {
2991 averagedX /= totalPressure;
2992 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07002993
2994#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07002995 LOGD("AveragingTouchFilter: Pointer id %d - "
2996 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2997 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07002998#endif
2999
Jeff Brown38a7fab2010-08-30 03:02:23 -07003000 mCurrentTouch.pointers[currentIndex].x = averagedX;
3001 mCurrentTouch.pointers[currentIndex].y = averagedY;
3002 }
Jeff Browne57e8952010-07-23 21:28:06 -07003003 } else {
3004#if DEBUG_HACKS
3005 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3006#endif
3007 }
3008 } else {
3009#if DEBUG_HACKS
3010 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3011#endif
3012 }
3013
3014 // Reset pointer history.
3015 mAveragingTouchFilter.historyStart[id] = 0;
3016 mAveragingTouchFilter.historyEnd[id] = 0;
3017 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3018 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3019 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3020 }
3021}
3022
3023int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003024 { // acquire lock
3025 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003026
Jeff Brownb51719b2010-07-29 18:18:33 -07003027 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003028 return AKEY_STATE_VIRTUAL;
3029 }
3030
Jeff Brownb51719b2010-07-29 18:18:33 -07003031 size_t numVirtualKeys = mLocked.virtualKeys.size();
3032 for (size_t i = 0; i < numVirtualKeys; i++) {
3033 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003034 if (virtualKey.keyCode == keyCode) {
3035 return AKEY_STATE_UP;
3036 }
3037 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003038 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003039
3040 return AKEY_STATE_UNKNOWN;
3041}
3042
3043int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003044 { // acquire lock
3045 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003046
Jeff Brownb51719b2010-07-29 18:18:33 -07003047 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003048 return AKEY_STATE_VIRTUAL;
3049 }
3050
Jeff Brownb51719b2010-07-29 18:18:33 -07003051 size_t numVirtualKeys = mLocked.virtualKeys.size();
3052 for (size_t i = 0; i < numVirtualKeys; i++) {
3053 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003054 if (virtualKey.scanCode == scanCode) {
3055 return AKEY_STATE_UP;
3056 }
3057 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003058 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003059
3060 return AKEY_STATE_UNKNOWN;
3061}
3062
3063bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3064 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003065 { // acquire lock
3066 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003067
Jeff Brownb51719b2010-07-29 18:18:33 -07003068 size_t numVirtualKeys = mLocked.virtualKeys.size();
3069 for (size_t i = 0; i < numVirtualKeys; i++) {
3070 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003071
3072 for (size_t i = 0; i < numCodes; i++) {
3073 if (virtualKey.keyCode == keyCodes[i]) {
3074 outFlags[i] = 1;
3075 }
3076 }
3077 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003078 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003079
3080 return true;
3081}
3082
3083
3084// --- SingleTouchInputMapper ---
3085
3086SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3087 TouchInputMapper(device, associatedDisplayId) {
3088 initialize();
3089}
3090
3091SingleTouchInputMapper::~SingleTouchInputMapper() {
3092}
3093
3094void SingleTouchInputMapper::initialize() {
3095 mAccumulator.clear();
3096
3097 mDown = false;
3098 mX = 0;
3099 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003100 mPressure = 0; // default to 0 for devices that don't report pressure
3101 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003102}
3103
3104void SingleTouchInputMapper::reset() {
3105 TouchInputMapper::reset();
3106
Jeff Browne57e8952010-07-23 21:28:06 -07003107 initialize();
3108 }
3109
3110void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3111 switch (rawEvent->type) {
3112 case EV_KEY:
3113 switch (rawEvent->scanCode) {
3114 case BTN_TOUCH:
3115 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3116 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003117 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3118 // not have received valid position information yet. This logic assumes that
3119 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003120 break;
3121 }
3122 break;
3123
3124 case EV_ABS:
3125 switch (rawEvent->scanCode) {
3126 case ABS_X:
3127 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3128 mAccumulator.absX = rawEvent->value;
3129 break;
3130 case ABS_Y:
3131 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3132 mAccumulator.absY = rawEvent->value;
3133 break;
3134 case ABS_PRESSURE:
3135 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3136 mAccumulator.absPressure = rawEvent->value;
3137 break;
3138 case ABS_TOOL_WIDTH:
3139 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3140 mAccumulator.absToolWidth = rawEvent->value;
3141 break;
3142 }
3143 break;
3144
3145 case EV_SYN:
3146 switch (rawEvent->scanCode) {
3147 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003148 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003149 break;
3150 }
3151 break;
3152 }
3153}
3154
3155void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003156 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003157 if (fields == 0) {
3158 return; // no new state changes, so nothing to do
3159 }
Jeff Browne57e8952010-07-23 21:28:06 -07003160
3161 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3162 mDown = mAccumulator.btnTouch;
3163 }
3164
3165 if (fields & Accumulator::FIELD_ABS_X) {
3166 mX = mAccumulator.absX;
3167 }
3168
3169 if (fields & Accumulator::FIELD_ABS_Y) {
3170 mY = mAccumulator.absY;
3171 }
3172
3173 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3174 mPressure = mAccumulator.absPressure;
3175 }
3176
3177 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003178 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003179 }
3180
3181 mCurrentTouch.clear();
3182
3183 if (mDown) {
3184 mCurrentTouch.pointerCount = 1;
3185 mCurrentTouch.pointers[0].id = 0;
3186 mCurrentTouch.pointers[0].x = mX;
3187 mCurrentTouch.pointers[0].y = mY;
3188 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003189 mCurrentTouch.pointers[0].touchMajor = 0;
3190 mCurrentTouch.pointers[0].touchMinor = 0;
3191 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3192 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003193 mCurrentTouch.pointers[0].orientation = 0;
3194 mCurrentTouch.idToIndex[0] = 0;
3195 mCurrentTouch.idBits.markBit(0);
3196 }
3197
3198 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003199
3200 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003201}
3202
Jeff Brown38a7fab2010-08-30 03:02:23 -07003203void SingleTouchInputMapper::configureRawAxes() {
3204 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003205
Jeff Brown38a7fab2010-08-30 03:02:23 -07003206 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3207 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3208 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3209 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003210}
3211
3212
3213// --- MultiTouchInputMapper ---
3214
3215MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3216 TouchInputMapper(device, associatedDisplayId) {
3217 initialize();
3218}
3219
3220MultiTouchInputMapper::~MultiTouchInputMapper() {
3221}
3222
3223void MultiTouchInputMapper::initialize() {
3224 mAccumulator.clear();
3225}
3226
3227void MultiTouchInputMapper::reset() {
3228 TouchInputMapper::reset();
3229
Jeff Browne57e8952010-07-23 21:28:06 -07003230 initialize();
3231}
3232
3233void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3234 switch (rawEvent->type) {
3235 case EV_ABS: {
3236 uint32_t pointerIndex = mAccumulator.pointerCount;
3237 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3238
3239 switch (rawEvent->scanCode) {
3240 case ABS_MT_POSITION_X:
3241 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3242 pointer->absMTPositionX = rawEvent->value;
3243 break;
3244 case ABS_MT_POSITION_Y:
3245 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3246 pointer->absMTPositionY = rawEvent->value;
3247 break;
3248 case ABS_MT_TOUCH_MAJOR:
3249 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3250 pointer->absMTTouchMajor = rawEvent->value;
3251 break;
3252 case ABS_MT_TOUCH_MINOR:
3253 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3254 pointer->absMTTouchMinor = rawEvent->value;
3255 break;
3256 case ABS_MT_WIDTH_MAJOR:
3257 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3258 pointer->absMTWidthMajor = rawEvent->value;
3259 break;
3260 case ABS_MT_WIDTH_MINOR:
3261 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3262 pointer->absMTWidthMinor = rawEvent->value;
3263 break;
3264 case ABS_MT_ORIENTATION:
3265 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3266 pointer->absMTOrientation = rawEvent->value;
3267 break;
3268 case ABS_MT_TRACKING_ID:
3269 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3270 pointer->absMTTrackingId = rawEvent->value;
3271 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003272 case ABS_MT_PRESSURE:
3273 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3274 pointer->absMTPressure = rawEvent->value;
3275 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003276 }
3277 break;
3278 }
3279
3280 case EV_SYN:
3281 switch (rawEvent->scanCode) {
3282 case SYN_MT_REPORT: {
3283 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3284 uint32_t pointerIndex = mAccumulator.pointerCount;
3285
3286 if (mAccumulator.pointers[pointerIndex].fields) {
3287 if (pointerIndex == MAX_POINTERS) {
3288 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3289 MAX_POINTERS);
3290 } else {
3291 pointerIndex += 1;
3292 mAccumulator.pointerCount = pointerIndex;
3293 }
3294 }
3295
3296 mAccumulator.pointers[pointerIndex].clear();
3297 break;
3298 }
3299
3300 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003301 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003302 break;
3303 }
3304 break;
3305 }
3306}
3307
3308void MultiTouchInputMapper::sync(nsecs_t when) {
3309 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003310 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003311
Jeff Browne57e8952010-07-23 21:28:06 -07003312 uint32_t inCount = mAccumulator.pointerCount;
3313 uint32_t outCount = 0;
3314 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003315
Jeff Browne57e8952010-07-23 21:28:06 -07003316 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003317
Jeff Browne57e8952010-07-23 21:28:06 -07003318 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003319 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3320 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003321
Jeff Browne57e8952010-07-23 21:28:06 -07003322 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003323 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3324 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003325 continue;
3326 }
3327
Jeff Brownd64c8552010-08-17 20:38:35 -07003328 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3329 outPointer.x = inPointer.absMTPositionX;
3330 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003331
Jeff Brown38a7fab2010-08-30 03:02:23 -07003332 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3333 if (inPointer.absMTPressure <= 0) {
3334 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brownd64c8552010-08-17 20:38:35 -07003335 // a pointer up. Drop this finger.
3336 continue;
3337 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003338 outPointer.pressure = inPointer.absMTPressure;
3339 } else {
3340 // Default pressure to 0 if absent.
3341 outPointer.pressure = 0;
3342 }
3343
3344 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3345 if (inPointer.absMTTouchMajor <= 0) {
3346 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3347 // a pointer going up. Drop this finger.
3348 continue;
3349 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003350 outPointer.touchMajor = inPointer.absMTTouchMajor;
3351 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003352 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003353 outPointer.touchMajor = 0;
3354 }
Jeff Browne839a582010-04-22 18:58:52 -07003355
Jeff Brownd64c8552010-08-17 20:38:35 -07003356 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3357 outPointer.touchMinor = inPointer.absMTTouchMinor;
3358 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003359 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003360 outPointer.touchMinor = outPointer.touchMajor;
3361 }
Jeff Browne839a582010-04-22 18:58:52 -07003362
Jeff Brownd64c8552010-08-17 20:38:35 -07003363 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3364 outPointer.toolMajor = inPointer.absMTWidthMajor;
3365 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003366 // Default tool area to 0 if absent.
3367 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003368 }
Jeff Browne839a582010-04-22 18:58:52 -07003369
Jeff Brownd64c8552010-08-17 20:38:35 -07003370 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3371 outPointer.toolMinor = inPointer.absMTWidthMinor;
3372 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003373 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003374 outPointer.toolMinor = outPointer.toolMajor;
3375 }
3376
3377 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3378 outPointer.orientation = inPointer.absMTOrientation;
3379 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003380 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003381 outPointer.orientation = 0;
3382 }
3383
Jeff Brown38a7fab2010-08-30 03:02:23 -07003384 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003385 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003386 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3387 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003388
Jeff Browne57e8952010-07-23 21:28:06 -07003389 if (id > MAX_POINTER_ID) {
3390#if DEBUG_POINTERS
3391 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003392 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003393 id, MAX_POINTER_ID);
3394#endif
3395 havePointerIds = false;
3396 }
3397 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003398 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003399 mCurrentTouch.idToIndex[id] = outCount;
3400 mCurrentTouch.idBits.markBit(id);
3401 }
3402 } else {
3403 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003404 }
3405 }
Jeff Browne839a582010-04-22 18:58:52 -07003406
Jeff Browne57e8952010-07-23 21:28:06 -07003407 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003408 }
3409
Jeff Browne57e8952010-07-23 21:28:06 -07003410 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003411
Jeff Browne57e8952010-07-23 21:28:06 -07003412 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003413
3414 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003415}
3416
Jeff Brown38a7fab2010-08-30 03:02:23 -07003417void MultiTouchInputMapper::configureRawAxes() {
3418 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003419
Jeff Brown38a7fab2010-08-30 03:02:23 -07003420 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3421 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3422 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3423 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3424 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3425 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3426 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3427 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003428}
3429
Jeff Browne839a582010-04-22 18:58:52 -07003430
3431} // namespace android