blob: ce0d8802384526cbf128bd5ba8f447aef9eee9f6 [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 Brown1ad00e92010-10-01 18:55:43 -0700229 addDevice(rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700230 break;
231
232 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown1ad00e92010-10-01 18:55:43 -0700233 removeDevice(rawEvent->deviceId);
234 break;
235
236 case EventHubInterface::FINISHED_DEVICE_SCAN:
237 handleConfigurationChanged();
Jeff Browne839a582010-04-22 18:58:52 -0700238 break;
239
Jeff Browne57e8952010-07-23 21:28:06 -0700240 default:
241 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700242 break;
243 }
244}
245
Jeff Brown1ad00e92010-10-01 18:55:43 -0700246void InputReader::addDevice(int32_t deviceId) {
Jeff Browne57e8952010-07-23 21:28:06 -0700247 String8 name = mEventHub->getDeviceName(deviceId);
248 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
249
250 InputDevice* device = createDevice(deviceId, name, classes);
251 device->configure();
252
Jeff Brown38a7fab2010-08-30 03:02:23 -0700253 if (device->isIgnored()) {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700254 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", deviceId, name.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700255 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700256 LOGI("Device added: id=0x%x, name=%s, sources=%08x", deviceId, name.string(),
257 device->getSources());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700258 }
259
Jeff Browne57e8952010-07-23 21:28:06 -0700260 bool added = false;
261 { // acquire device registry writer lock
262 RWLock::AutoWLock _wl(mDeviceRegistryLock);
263
264 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
265 if (deviceIndex < 0) {
266 mDevices.add(deviceId, device);
267 added = true;
268 }
269 } // release device registry writer lock
270
271 if (! added) {
272 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
273 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700274 return;
275 }
Jeff Browne839a582010-04-22 18:58:52 -0700276}
277
Jeff Brown1ad00e92010-10-01 18:55:43 -0700278void InputReader::removeDevice(int32_t deviceId) {
Jeff Browne57e8952010-07-23 21:28:06 -0700279 bool removed = false;
280 InputDevice* device = NULL;
281 { // acquire device registry writer lock
282 RWLock::AutoWLock _wl(mDeviceRegistryLock);
283
284 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
285 if (deviceIndex >= 0) {
286 device = mDevices.valueAt(deviceIndex);
287 mDevices.removeItemsAt(deviceIndex, 1);
288 removed = true;
289 }
290 } // release device registry writer lock
291
292 if (! removed) {
293 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700294 return;
295 }
296
Jeff Browne57e8952010-07-23 21:28:06 -0700297 if (device->isIgnored()) {
298 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
299 device->getId(), device->getName().string());
300 } else {
301 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
302 device->getId(), device->getName().string(), device->getSources());
303 }
304
Jeff Brown38a7fab2010-08-30 03:02:23 -0700305 device->reset();
306
Jeff Browne57e8952010-07-23 21:28:06 -0700307 delete device;
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
Jeff Brown1ad00e92010-10-01 18:55:43 -0700375void InputReader::handleConfigurationChanged() {
Jeff Browne57e8952010-07-23 21:28:06 -0700376 // 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.
Jeff Brown1ad00e92010-10-01 18:55:43 -0700383 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browne57e8952010-07-23 21:28:06 -0700384 mDispatcher->notifyConfigurationChanged(when);
385}
386
387void InputReader::configureExcludedDevices() {
388 Vector<String8> excludedDeviceNames;
389 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
390
391 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
392 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
393 }
394}
395
396void InputReader::updateGlobalMetaState() {
397 { // acquire state lock
398 AutoMutex _l(mStateLock);
399
400 mGlobalMetaState = 0;
401
402 { // acquire device registry reader lock
403 RWLock::AutoRLock _rl(mDeviceRegistryLock);
404
405 for (size_t i = 0; i < mDevices.size(); i++) {
406 InputDevice* device = mDevices.valueAt(i);
407 mGlobalMetaState |= device->getMetaState();
408 }
409 } // release device registry reader lock
410 } // release state lock
411}
412
413int32_t InputReader::getGlobalMetaState() {
414 { // acquire state lock
415 AutoMutex _l(mStateLock);
416
417 return mGlobalMetaState;
418 } // release state lock
419}
420
421void InputReader::updateInputConfiguration() {
422 { // acquire state lock
423 AutoMutex _l(mStateLock);
424
425 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
426 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
427 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
428 { // acquire device registry reader lock
429 RWLock::AutoRLock _rl(mDeviceRegistryLock);
430
431 InputDeviceInfo deviceInfo;
432 for (size_t i = 0; i < mDevices.size(); i++) {
433 InputDevice* device = mDevices.valueAt(i);
434 device->getDeviceInfo(& deviceInfo);
435 uint32_t sources = deviceInfo.getSources();
436
437 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
438 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
439 }
440 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
441 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
442 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
443 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
444 }
445 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
446 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Browne839a582010-04-22 18:58:52 -0700447 }
448 }
Jeff Browne57e8952010-07-23 21:28:06 -0700449 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700450
Jeff Browne57e8952010-07-23 21:28:06 -0700451 mInputConfiguration.touchScreen = touchScreenConfig;
452 mInputConfiguration.keyboard = keyboardConfig;
453 mInputConfiguration.navigation = navigationConfig;
454 } // release state lock
455}
456
457void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
458 { // acquire state lock
459 AutoMutex _l(mStateLock);
460
461 *outConfiguration = mInputConfiguration;
462 } // release state lock
463}
464
465status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
466 { // acquire device registry reader lock
467 RWLock::AutoRLock _rl(mDeviceRegistryLock);
468
469 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
470 if (deviceIndex < 0) {
471 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700472 }
473
Jeff Browne57e8952010-07-23 21:28:06 -0700474 InputDevice* device = mDevices.valueAt(deviceIndex);
475 if (device->isIgnored()) {
476 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700477 }
Jeff Browne57e8952010-07-23 21:28:06 -0700478
479 device->getDeviceInfo(outDeviceInfo);
480 return OK;
481 } // release device registy reader lock
482}
483
484void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
485 outDeviceIds.clear();
486
487 { // acquire device registry reader lock
488 RWLock::AutoRLock _rl(mDeviceRegistryLock);
489
490 size_t numDevices = mDevices.size();
491 for (size_t i = 0; i < numDevices; i++) {
492 InputDevice* device = mDevices.valueAt(i);
493 if (! device->isIgnored()) {
494 outDeviceIds.add(device->getId());
495 }
496 }
497 } // release device registy reader lock
498}
499
500int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
501 int32_t keyCode) {
502 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
503}
504
505int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
506 int32_t scanCode) {
507 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
508}
509
510int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
511 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
512}
513
514int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
515 GetStateFunc getStateFunc) {
516 { // acquire device registry reader lock
517 RWLock::AutoRLock _rl(mDeviceRegistryLock);
518
519 int32_t result = AKEY_STATE_UNKNOWN;
520 if (deviceId >= 0) {
521 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
522 if (deviceIndex >= 0) {
523 InputDevice* device = mDevices.valueAt(deviceIndex);
524 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
525 result = (device->*getStateFunc)(sourceMask, code);
526 }
527 }
528 } else {
529 size_t numDevices = mDevices.size();
530 for (size_t i = 0; i < numDevices; i++) {
531 InputDevice* device = mDevices.valueAt(i);
532 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
533 result = (device->*getStateFunc)(sourceMask, code);
534 if (result >= AKEY_STATE_DOWN) {
535 return result;
536 }
537 }
538 }
539 }
540 return result;
541 } // release device registy reader lock
542}
543
544bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
545 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
546 memset(outFlags, 0, numCodes);
547 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
548}
549
550bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
551 const int32_t* keyCodes, uint8_t* outFlags) {
552 { // acquire device registry reader lock
553 RWLock::AutoRLock _rl(mDeviceRegistryLock);
554 bool result = false;
555 if (deviceId >= 0) {
556 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
557 if (deviceIndex >= 0) {
558 InputDevice* device = mDevices.valueAt(deviceIndex);
559 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
560 result = device->markSupportedKeyCodes(sourceMask,
561 numCodes, keyCodes, outFlags);
562 }
563 }
564 } else {
565 size_t numDevices = mDevices.size();
566 for (size_t i = 0; i < numDevices; i++) {
567 InputDevice* device = mDevices.valueAt(i);
568 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
569 result |= device->markSupportedKeyCodes(sourceMask,
570 numCodes, keyCodes, outFlags);
571 }
572 }
573 }
574 return result;
575 } // release device registy reader lock
576}
577
Jeff Browna665ca82010-09-08 11:49:43 -0700578void InputReader::dump(String8& dump) {
Jeff Brown2806e382010-10-01 17:46:21 -0700579 mEventHub->dump(dump);
580 dump.append("\n");
581
582 dump.append("Input Reader State:\n");
583
Jeff Brown26c94ff2010-09-30 14:33:04 -0700584 { // acquire device registry reader lock
585 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Browna665ca82010-09-08 11:49:43 -0700586
Jeff Brown26c94ff2010-09-30 14:33:04 -0700587 for (size_t i = 0; i < mDevices.size(); i++) {
588 mDevices.valueAt(i)->dump(dump);
Jeff Browna665ca82010-09-08 11:49:43 -0700589 }
Jeff Brown26c94ff2010-09-30 14:33:04 -0700590 } // release device registy reader lock
Jeff Browna665ca82010-09-08 11:49:43 -0700591}
592
Jeff Browne57e8952010-07-23 21:28:06 -0700593
594// --- InputReaderThread ---
595
596InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
597 Thread(/*canCallJava*/ true), mReader(reader) {
598}
599
600InputReaderThread::~InputReaderThread() {
601}
602
603bool InputReaderThread::threadLoop() {
604 mReader->loopOnce();
605 return true;
606}
607
608
609// --- InputDevice ---
610
611InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
612 mContext(context), mId(id), mName(name), mSources(0) {
613}
614
615InputDevice::~InputDevice() {
616 size_t numMappers = mMappers.size();
617 for (size_t i = 0; i < numMappers; i++) {
618 delete mMappers[i];
619 }
620 mMappers.clear();
621}
622
Jeff Brown26c94ff2010-09-30 14:33:04 -0700623static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
624 int32_t rangeType, const char* name) {
625 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
626 if (range) {
627 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
628 name, range->min, range->max, range->flat, range->fuzz);
629 }
630}
631
632void InputDevice::dump(String8& dump) {
633 InputDeviceInfo deviceInfo;
634 getDeviceInfo(& deviceInfo);
635
636 dump.appendFormat(INDENT "Device 0x%x: %s\n", deviceInfo.getId(),
637 deviceInfo.getName().string());
638 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
639 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
640 if (!deviceInfo.getMotionRanges().isEmpty()) {
641 dump.append(INDENT2 "Motion Ranges:\n");
642 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
643 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
644 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
645 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
646 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
647 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
648 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
649 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
650 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
651 }
652
653 size_t numMappers = mMappers.size();
654 for (size_t i = 0; i < numMappers; i++) {
655 InputMapper* mapper = mMappers[i];
656 mapper->dump(dump);
657 }
658}
659
Jeff Browne57e8952010-07-23 21:28:06 -0700660void InputDevice::addMapper(InputMapper* mapper) {
661 mMappers.add(mapper);
662}
663
664void InputDevice::configure() {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700665 if (! isIgnored()) {
666 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
667 }
668
Jeff Browne57e8952010-07-23 21:28:06 -0700669 mSources = 0;
670
671 size_t numMappers = mMappers.size();
672 for (size_t i = 0; i < numMappers; i++) {
673 InputMapper* mapper = mMappers[i];
674 mapper->configure();
675 mSources |= mapper->getSources();
Jeff Browne839a582010-04-22 18:58:52 -0700676 }
677}
678
Jeff Browne57e8952010-07-23 21:28:06 -0700679void InputDevice::reset() {
680 size_t numMappers = mMappers.size();
681 for (size_t i = 0; i < numMappers; i++) {
682 InputMapper* mapper = mMappers[i];
683 mapper->reset();
684 }
685}
Jeff Browne839a582010-04-22 18:58:52 -0700686
Jeff Browne57e8952010-07-23 21:28:06 -0700687void InputDevice::process(const RawEvent* rawEvent) {
688 size_t numMappers = mMappers.size();
689 for (size_t i = 0; i < numMappers; i++) {
690 InputMapper* mapper = mMappers[i];
691 mapper->process(rawEvent);
692 }
693}
Jeff Browne839a582010-04-22 18:58:52 -0700694
Jeff Browne57e8952010-07-23 21:28:06 -0700695void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
696 outDeviceInfo->initialize(mId, mName);
697
698 size_t numMappers = mMappers.size();
699 for (size_t i = 0; i < numMappers; i++) {
700 InputMapper* mapper = mMappers[i];
701 mapper->populateDeviceInfo(outDeviceInfo);
702 }
703}
704
705int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
706 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
707}
708
709int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
710 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
711}
712
713int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
714 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
715}
716
717int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
718 int32_t result = AKEY_STATE_UNKNOWN;
719 size_t numMappers = mMappers.size();
720 for (size_t i = 0; i < numMappers; i++) {
721 InputMapper* mapper = mMappers[i];
722 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
723 result = (mapper->*getStateFunc)(sourceMask, code);
724 if (result >= AKEY_STATE_DOWN) {
725 return result;
726 }
727 }
728 }
729 return result;
730}
731
732bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
733 const int32_t* keyCodes, uint8_t* outFlags) {
734 bool result = false;
735 size_t numMappers = mMappers.size();
736 for (size_t i = 0; i < numMappers; i++) {
737 InputMapper* mapper = mMappers[i];
738 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
739 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
740 }
741 }
742 return result;
743}
744
745int32_t InputDevice::getMetaState() {
746 int32_t result = 0;
747 size_t numMappers = mMappers.size();
748 for (size_t i = 0; i < numMappers; i++) {
749 InputMapper* mapper = mMappers[i];
750 result |= mapper->getMetaState();
751 }
752 return result;
753}
754
755
756// --- InputMapper ---
757
758InputMapper::InputMapper(InputDevice* device) :
759 mDevice(device), mContext(device->getContext()) {
760}
761
762InputMapper::~InputMapper() {
763}
764
765void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
766 info->addSource(getSources());
767}
768
Jeff Brown26c94ff2010-09-30 14:33:04 -0700769void InputMapper::dump(String8& dump) {
770}
771
Jeff Browne57e8952010-07-23 21:28:06 -0700772void InputMapper::configure() {
773}
774
775void InputMapper::reset() {
776}
777
778int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
779 return AKEY_STATE_UNKNOWN;
780}
781
782int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
783 return AKEY_STATE_UNKNOWN;
784}
785
786int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
787 return AKEY_STATE_UNKNOWN;
788}
789
790bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
791 const int32_t* keyCodes, uint8_t* outFlags) {
792 return false;
793}
794
795int32_t InputMapper::getMetaState() {
796 return 0;
797}
798
Jeff Browne57e8952010-07-23 21:28:06 -0700799
800// --- SwitchInputMapper ---
801
802SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
803 InputMapper(device) {
804}
805
806SwitchInputMapper::~SwitchInputMapper() {
807}
808
809uint32_t SwitchInputMapper::getSources() {
810 return 0;
811}
812
813void SwitchInputMapper::process(const RawEvent* rawEvent) {
814 switch (rawEvent->type) {
815 case EV_SW:
816 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
817 break;
818 }
819}
820
821void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brown90f0cee2010-10-08 22:31:17 -0700822 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700823}
824
825int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
826 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
827}
828
829
830// --- KeyboardInputMapper ---
831
832KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
833 uint32_t sources, int32_t keyboardType) :
834 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
835 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700836 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700837}
838
839KeyboardInputMapper::~KeyboardInputMapper() {
840}
841
Jeff Brownb51719b2010-07-29 18:18:33 -0700842void KeyboardInputMapper::initializeLocked() {
843 mLocked.metaState = AMETA_NONE;
844 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700845}
846
847uint32_t KeyboardInputMapper::getSources() {
848 return mSources;
849}
850
851void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
852 InputMapper::populateDeviceInfo(info);
853
854 info->setKeyboardType(mKeyboardType);
855}
856
Jeff Brown26c94ff2010-09-30 14:33:04 -0700857void KeyboardInputMapper::dump(String8& dump) {
858 { // acquire lock
859 AutoMutex _l(mLock);
860 dump.append(INDENT2 "Keyboard Input Mapper:\n");
861 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
Jeff Brown26c94ff2010-09-30 14:33:04 -0700862 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
863 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
864 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
865 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
866 } // release lock
867}
868
Jeff Browne57e8952010-07-23 21:28:06 -0700869void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700870 for (;;) {
871 int32_t keyCode, scanCode;
872 { // acquire lock
873 AutoMutex _l(mLock);
874
875 // Synthesize key up event on reset if keys are currently down.
876 if (mLocked.keyDowns.isEmpty()) {
877 initializeLocked();
878 break; // done
879 }
880
881 const KeyDown& keyDown = mLocked.keyDowns.top();
882 keyCode = keyDown.keyCode;
883 scanCode = keyDown.scanCode;
884 } // release lock
885
Jeff Browne57e8952010-07-23 21:28:06 -0700886 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700887 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700888 }
889
890 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700891 getContext()->updateGlobalMetaState();
892}
893
894void KeyboardInputMapper::process(const RawEvent* rawEvent) {
895 switch (rawEvent->type) {
896 case EV_KEY: {
897 int32_t scanCode = rawEvent->scanCode;
898 if (isKeyboardOrGamepadKey(scanCode)) {
899 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
900 rawEvent->flags);
901 }
902 break;
903 }
904 }
905}
906
907bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
908 return scanCode < BTN_MOUSE
909 || scanCode >= KEY_OK
910 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
911}
912
Jeff Brownb51719b2010-07-29 18:18:33 -0700913void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
914 int32_t scanCode, uint32_t policyFlags) {
915 int32_t newMetaState;
916 nsecs_t downTime;
917 bool metaStateChanged = false;
918
919 { // acquire lock
920 AutoMutex _l(mLock);
921
922 if (down) {
923 // Rotate key codes according to orientation if needed.
924 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
925 if (mAssociatedDisplayId >= 0) {
926 int32_t orientation;
927 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
928 return;
929 }
930
931 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700932 }
933
Jeff Brownb51719b2010-07-29 18:18:33 -0700934 // Add key down.
935 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
936 if (keyDownIndex >= 0) {
937 // key repeat, be sure to use same keycode as before in case of rotation
938 keyCode = mLocked.keyDowns.top().keyCode;
939 } else {
940 // key down
941 mLocked.keyDowns.push();
942 KeyDown& keyDown = mLocked.keyDowns.editTop();
943 keyDown.keyCode = keyCode;
944 keyDown.scanCode = scanCode;
945 }
946
947 mLocked.downTime = when;
948 } else {
949 // Remove key down.
950 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
951 if (keyDownIndex >= 0) {
952 // key up, be sure to use same keycode as before in case of rotation
953 keyCode = mLocked.keyDowns.top().keyCode;
954 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
955 } else {
956 // key was not actually down
957 LOGI("Dropping key up from device %s because the key was not down. "
958 "keyCode=%d, scanCode=%d",
959 getDeviceName().string(), keyCode, scanCode);
960 return;
961 }
Jeff Browne57e8952010-07-23 21:28:06 -0700962 }
963
Jeff Brownb51719b2010-07-29 18:18:33 -0700964 int32_t oldMetaState = mLocked.metaState;
965 newMetaState = updateMetaState(keyCode, down, oldMetaState);
966 if (oldMetaState != newMetaState) {
967 mLocked.metaState = newMetaState;
968 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700969 }
Jeff Brown8575a872010-06-30 16:10:35 -0700970
Jeff Brownb51719b2010-07-29 18:18:33 -0700971 downTime = mLocked.downTime;
972 } // release lock
973
974 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700975 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700976 }
977
Jeff Browne57e8952010-07-23 21:28:06 -0700978 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown90f0cee2010-10-08 22:31:17 -0700979 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
980 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700981}
982
Jeff Brownb51719b2010-07-29 18:18:33 -0700983ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
984 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -0700985 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700986 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -0700987 return i;
988 }
989 }
990 return -1;
Jeff Browne839a582010-04-22 18:58:52 -0700991}
992
Jeff Browne57e8952010-07-23 21:28:06 -0700993int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
994 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
995}
Jeff Browne839a582010-04-22 18:58:52 -0700996
Jeff Browne57e8952010-07-23 21:28:06 -0700997int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
998 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
999}
Jeff Browne839a582010-04-22 18:58:52 -07001000
Jeff Browne57e8952010-07-23 21:28:06 -07001001bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1002 const int32_t* keyCodes, uint8_t* outFlags) {
1003 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1004}
1005
1006int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001007 { // acquire lock
1008 AutoMutex _l(mLock);
1009 return mLocked.metaState;
1010 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001011}
1012
1013
1014// --- TrackballInputMapper ---
1015
1016TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1017 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1018 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1019 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1020 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1021 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1022
Jeff Brownb51719b2010-07-29 18:18:33 -07001023 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001024}
1025
1026TrackballInputMapper::~TrackballInputMapper() {
1027}
1028
1029uint32_t TrackballInputMapper::getSources() {
1030 return AINPUT_SOURCE_TRACKBALL;
1031}
1032
1033void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1034 InputMapper::populateDeviceInfo(info);
1035
1036 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1037 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1038}
1039
Jeff Brown26c94ff2010-09-30 14:33:04 -07001040void TrackballInputMapper::dump(String8& dump) {
1041 { // acquire lock
1042 AutoMutex _l(mLock);
1043 dump.append(INDENT2 "Trackball Input Mapper:\n");
1044 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1045 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1046 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1047 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1048 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1049 } // release lock
1050}
1051
Jeff Brownb51719b2010-07-29 18:18:33 -07001052void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001053 mAccumulator.clear();
1054
Jeff Brownb51719b2010-07-29 18:18:33 -07001055 mLocked.down = false;
1056 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001057}
1058
1059void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001060 for (;;) {
1061 { // acquire lock
1062 AutoMutex _l(mLock);
1063
1064 if (! mLocked.down) {
1065 initializeLocked();
1066 break; // done
1067 }
1068 } // release lock
1069
1070 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001071 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001072 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001073 mAccumulator.btnMouse = false;
1074 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001075 }
1076
Jeff Browne57e8952010-07-23 21:28:06 -07001077 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001078}
Jeff Browne839a582010-04-22 18:58:52 -07001079
Jeff Browne57e8952010-07-23 21:28:06 -07001080void TrackballInputMapper::process(const RawEvent* rawEvent) {
1081 switch (rawEvent->type) {
1082 case EV_KEY:
1083 switch (rawEvent->scanCode) {
1084 case BTN_MOUSE:
1085 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1086 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001087 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1088 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001089 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001090 break;
Jeff Browne839a582010-04-22 18:58:52 -07001091 }
Jeff Browne57e8952010-07-23 21:28:06 -07001092 break;
Jeff Browne839a582010-04-22 18:58:52 -07001093
Jeff Browne57e8952010-07-23 21:28:06 -07001094 case EV_REL:
1095 switch (rawEvent->scanCode) {
1096 case REL_X:
1097 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1098 mAccumulator.relX = rawEvent->value;
1099 break;
1100 case REL_Y:
1101 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1102 mAccumulator.relY = rawEvent->value;
1103 break;
Jeff Browne839a582010-04-22 18:58:52 -07001104 }
Jeff Browne57e8952010-07-23 21:28:06 -07001105 break;
Jeff Browne839a582010-04-22 18:58:52 -07001106
Jeff Browne57e8952010-07-23 21:28:06 -07001107 case EV_SYN:
1108 switch (rawEvent->scanCode) {
1109 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001110 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001111 break;
Jeff Browne839a582010-04-22 18:58:52 -07001112 }
Jeff Browne57e8952010-07-23 21:28:06 -07001113 break;
Jeff Browne839a582010-04-22 18:58:52 -07001114 }
Jeff Browne839a582010-04-22 18:58:52 -07001115}
1116
Jeff Browne57e8952010-07-23 21:28:06 -07001117void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001118 uint32_t fields = mAccumulator.fields;
1119 if (fields == 0) {
1120 return; // no new state changes, so nothing to do
1121 }
1122
Jeff Brownb51719b2010-07-29 18:18:33 -07001123 int motionEventAction;
1124 PointerCoords pointerCoords;
1125 nsecs_t downTime;
1126 { // acquire lock
1127 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001128
Jeff Brownb51719b2010-07-29 18:18:33 -07001129 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1130
1131 if (downChanged) {
1132 if (mAccumulator.btnMouse) {
1133 mLocked.down = true;
1134 mLocked.downTime = when;
1135 } else {
1136 mLocked.down = false;
1137 }
Jeff Browne57e8952010-07-23 21:28:06 -07001138 }
Jeff Browne839a582010-04-22 18:58:52 -07001139
Jeff Brownb51719b2010-07-29 18:18:33 -07001140 downTime = mLocked.downTime;
1141 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1142 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001143
Jeff Brownb51719b2010-07-29 18:18:33 -07001144 if (downChanged) {
1145 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001146 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001147 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001148 }
Jeff Browne839a582010-04-22 18:58:52 -07001149
Jeff Brownb51719b2010-07-29 18:18:33 -07001150 pointerCoords.x = x;
1151 pointerCoords.y = y;
1152 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1153 pointerCoords.size = 0;
1154 pointerCoords.touchMajor = 0;
1155 pointerCoords.touchMinor = 0;
1156 pointerCoords.toolMajor = 0;
1157 pointerCoords.toolMinor = 0;
1158 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001159
Jeff Brownb51719b2010-07-29 18:18:33 -07001160 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1161 // Rotate motion based on display orientation if needed.
1162 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1163 int32_t orientation;
1164 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1165 return;
1166 }
1167
1168 float temp;
1169 switch (orientation) {
1170 case InputReaderPolicyInterface::ROTATION_90:
1171 temp = pointerCoords.x;
1172 pointerCoords.x = pointerCoords.y;
1173 pointerCoords.y = - temp;
1174 break;
1175
1176 case InputReaderPolicyInterface::ROTATION_180:
1177 pointerCoords.x = - pointerCoords.x;
1178 pointerCoords.y = - pointerCoords.y;
1179 break;
1180
1181 case InputReaderPolicyInterface::ROTATION_270:
1182 temp = pointerCoords.x;
1183 pointerCoords.x = - pointerCoords.y;
1184 pointerCoords.y = temp;
1185 break;
1186 }
1187 }
1188 } // release lock
1189
Jeff Browne57e8952010-07-23 21:28:06 -07001190 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001191 int32_t pointerId = 0;
Jeff Brown90f0cee2010-10-08 22:31:17 -07001192 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001193 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown90f0cee2010-10-08 22:31:17 -07001194 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1195
1196 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001197}
1198
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001199int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1200 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1201 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1202 } else {
1203 return AKEY_STATE_UNKNOWN;
1204 }
1205}
1206
Jeff Browne57e8952010-07-23 21:28:06 -07001207
1208// --- TouchInputMapper ---
1209
1210TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001211 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1212 mLocked.surfaceOrientation = -1;
1213 mLocked.surfaceWidth = -1;
1214 mLocked.surfaceHeight = -1;
1215
1216 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001217}
1218
1219TouchInputMapper::~TouchInputMapper() {
1220}
1221
1222uint32_t TouchInputMapper::getSources() {
1223 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1224}
1225
1226void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1227 InputMapper::populateDeviceInfo(info);
1228
Jeff Brownb51719b2010-07-29 18:18:33 -07001229 { // acquire lock
1230 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001231
Jeff Brownb51719b2010-07-29 18:18:33 -07001232 // Ensure surface information is up to date so that orientation changes are
1233 // noticed immediately.
1234 configureSurfaceLocked();
1235
1236 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1237 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001238
1239 if (mLocked.orientedRanges.havePressure) {
1240 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1241 mLocked.orientedRanges.pressure);
1242 }
1243
1244 if (mLocked.orientedRanges.haveSize) {
1245 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1246 mLocked.orientedRanges.size);
1247 }
1248
Jeff Brown6b337e72010-10-14 21:42:15 -07001249 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001250 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1251 mLocked.orientedRanges.touchMajor);
1252 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1253 mLocked.orientedRanges.touchMinor);
1254 }
1255
Jeff Brown6b337e72010-10-14 21:42:15 -07001256 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001257 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1258 mLocked.orientedRanges.toolMajor);
1259 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1260 mLocked.orientedRanges.toolMinor);
1261 }
1262
1263 if (mLocked.orientedRanges.haveOrientation) {
1264 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1265 mLocked.orientedRanges.orientation);
1266 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001267 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001268}
1269
Jeff Brown26c94ff2010-09-30 14:33:04 -07001270void TouchInputMapper::dump(String8& dump) {
1271 { // acquire lock
1272 AutoMutex _l(mLock);
1273 dump.append(INDENT2 "Touch Input Mapper:\n");
1274 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1275 dumpParameters(dump);
1276 dumpVirtualKeysLocked(dump);
1277 dumpRawAxes(dump);
1278 dumpCalibration(dump);
1279 dumpSurfaceLocked(dump);
Jeff Brown6b337e72010-10-14 21:42:15 -07001280 dump.appendFormat(INDENT3 "Translation and Scaling Factors:");
1281 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1282 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1283 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1284 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1285 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1286 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1287 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1288 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1289 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1290 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1291 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1292 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1293 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1294 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brown26c94ff2010-09-30 14:33:04 -07001295 } // release lock
1296}
1297
Jeff Brownb51719b2010-07-29 18:18:33 -07001298void TouchInputMapper::initializeLocked() {
1299 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001300 mLastTouch.clear();
1301 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001302
1303 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1304 mAveragingTouchFilter.historyStart[i] = 0;
1305 mAveragingTouchFilter.historyEnd[i] = 0;
1306 }
1307
1308 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001309
1310 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001311
1312 mLocked.orientedRanges.havePressure = false;
1313 mLocked.orientedRanges.haveSize = false;
Jeff Brown6b337e72010-10-14 21:42:15 -07001314 mLocked.orientedRanges.haveTouchSize = false;
1315 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001316 mLocked.orientedRanges.haveOrientation = false;
1317}
1318
Jeff Browne57e8952010-07-23 21:28:06 -07001319void TouchInputMapper::configure() {
1320 InputMapper::configure();
1321
1322 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001323 configureParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001324
1325 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001326 configureRawAxes();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001327
1328 // Prepare input device calibration.
1329 parseCalibration();
1330 resolveCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001331
Jeff Brownb51719b2010-07-29 18:18:33 -07001332 { // acquire lock
1333 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001334
Jeff Brown38a7fab2010-08-30 03:02:23 -07001335 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001336 configureSurfaceLocked();
1337 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001338}
1339
Jeff Brown38a7fab2010-08-30 03:02:23 -07001340void TouchInputMapper::configureParameters() {
1341 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1342 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1343 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1344}
1345
Jeff Brown26c94ff2010-09-30 14:33:04 -07001346void TouchInputMapper::dumpParameters(String8& dump) {
1347 dump.appendFormat(INDENT3 "UseBadTouchFilter: %s\n",
1348 toString(mParameters.useBadTouchFilter));
1349 dump.appendFormat(INDENT3 "UseAveragingTouchFilter: %s\n",
1350 toString(mParameters.useAveragingTouchFilter));
1351 dump.appendFormat(INDENT3 "UseJumpyTouchFilter: %s\n",
1352 toString(mParameters.useJumpyTouchFilter));
Jeff Browna665ca82010-09-08 11:49:43 -07001353}
1354
Jeff Brown38a7fab2010-08-30 03:02:23 -07001355void TouchInputMapper::configureRawAxes() {
1356 mRawAxes.x.clear();
1357 mRawAxes.y.clear();
1358 mRawAxes.pressure.clear();
1359 mRawAxes.touchMajor.clear();
1360 mRawAxes.touchMinor.clear();
1361 mRawAxes.toolMajor.clear();
1362 mRawAxes.toolMinor.clear();
1363 mRawAxes.orientation.clear();
1364}
1365
Jeff Brown26c94ff2010-09-30 14:33:04 -07001366static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Browna665ca82010-09-08 11:49:43 -07001367 if (axis.valid) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001368 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Browna665ca82010-09-08 11:49:43 -07001369 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1370 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001371 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Browna665ca82010-09-08 11:49:43 -07001372 }
1373}
1374
Jeff Brown26c94ff2010-09-30 14:33:04 -07001375void TouchInputMapper::dumpRawAxes(String8& dump) {
1376 dump.append(INDENT3 "Raw Axes:\n");
1377 dumpAxisInfo(dump, mRawAxes.x, "X");
1378 dumpAxisInfo(dump, mRawAxes.y, "Y");
1379 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1380 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1381 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1382 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1383 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1384 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001385}
1386
Jeff Brownb51719b2010-07-29 18:18:33 -07001387bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001388 // Update orientation and dimensions if needed.
1389 int32_t orientation;
1390 int32_t width, height;
1391 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001392 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001393 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1394 return false;
1395 }
1396 } else {
1397 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001398 width = mRawAxes.x.getRange();
1399 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001400 }
1401
Jeff Brownb51719b2010-07-29 18:18:33 -07001402 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001403 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001404 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001405 }
1406
Jeff Brownb51719b2010-07-29 18:18:33 -07001407 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001408 if (sizeChanged) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001409 LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
1410 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001411
Jeff Brownb51719b2010-07-29 18:18:33 -07001412 mLocked.surfaceWidth = width;
1413 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001414
Jeff Brown38a7fab2010-08-30 03:02:23 -07001415 // Configure X and Y factors.
1416 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1417 mLocked.xOrigin = mRawAxes.x.minValue;
1418 mLocked.yOrigin = mRawAxes.y.minValue;
1419 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1420 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001421 mLocked.xPrecision = 1.0f / mLocked.xScale;
1422 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001423
Jeff Brownb51719b2010-07-29 18:18:33 -07001424 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001425 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001426 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001427 mLocked.xOrigin = 0;
1428 mLocked.yOrigin = 0;
1429 mLocked.xScale = 1.0f;
1430 mLocked.yScale = 1.0f;
1431 mLocked.xPrecision = 1.0f;
1432 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001433 }
1434
Jeff Brown38a7fab2010-08-30 03:02:23 -07001435 // Scale factor for terms that are not oriented in a particular axis.
1436 // If the pixels are square then xScale == yScale otherwise we fake it
1437 // by choosing an average.
1438 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001439
Jeff Brown38a7fab2010-08-30 03:02:23 -07001440 // Size of diagonal axis.
1441 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001442
Jeff Brown38a7fab2010-08-30 03:02:23 -07001443 // TouchMajor and TouchMinor factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001444 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1445 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001446 mLocked.orientedRanges.touchMajor.min = 0;
1447 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1448 mLocked.orientedRanges.touchMajor.flat = 0;
1449 mLocked.orientedRanges.touchMajor.fuzz = 0;
1450 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1451 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001452
Jeff Brown38a7fab2010-08-30 03:02:23 -07001453 // ToolMajor and ToolMinor factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001454 mLocked.toolSizeLinearScale = 0;
1455 mLocked.toolSizeLinearBias = 0;
1456 mLocked.toolSizeAreaScale = 0;
1457 mLocked.toolSizeAreaBias = 0;
1458 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1459 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1460 if (mCalibration.haveToolSizeLinearScale) {
1461 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001462 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brown6b337e72010-10-14 21:42:15 -07001463 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown38a7fab2010-08-30 03:02:23 -07001464 / mRawAxes.toolMajor.maxValue;
1465 }
1466
Jeff Brown6b337e72010-10-14 21:42:15 -07001467 if (mCalibration.haveToolSizeLinearBias) {
1468 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1469 }
1470 } else if (mCalibration.toolSizeCalibration ==
1471 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1472 if (mCalibration.haveToolSizeLinearScale) {
1473 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1474 } else {
1475 mLocked.toolSizeLinearScale = min(width, height);
1476 }
1477
1478 if (mCalibration.haveToolSizeLinearBias) {
1479 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1480 }
1481
1482 if (mCalibration.haveToolSizeAreaScale) {
1483 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1484 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1485 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1486 }
1487
1488 if (mCalibration.haveToolSizeAreaBias) {
1489 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001490 }
1491 }
1492
Jeff Brown6b337e72010-10-14 21:42:15 -07001493 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001494 mLocked.orientedRanges.toolMajor.min = 0;
1495 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1496 mLocked.orientedRanges.toolMajor.flat = 0;
1497 mLocked.orientedRanges.toolMajor.fuzz = 0;
1498 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1499 }
1500
1501 // Pressure factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001502 mLocked.pressureScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001503 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1504 RawAbsoluteAxisInfo rawPressureAxis;
1505 switch (mCalibration.pressureSource) {
1506 case Calibration::PRESSURE_SOURCE_PRESSURE:
1507 rawPressureAxis = mRawAxes.pressure;
1508 break;
1509 case Calibration::PRESSURE_SOURCE_TOUCH:
1510 rawPressureAxis = mRawAxes.touchMajor;
1511 break;
1512 default:
1513 rawPressureAxis.clear();
1514 }
1515
Jeff Brown38a7fab2010-08-30 03:02:23 -07001516 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1517 || mCalibration.pressureCalibration
1518 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1519 if (mCalibration.havePressureScale) {
1520 mLocked.pressureScale = mCalibration.pressureScale;
1521 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1522 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1523 }
1524 }
1525
1526 mLocked.orientedRanges.havePressure = true;
1527 mLocked.orientedRanges.pressure.min = 0;
1528 mLocked.orientedRanges.pressure.max = 1.0;
1529 mLocked.orientedRanges.pressure.flat = 0;
1530 mLocked.orientedRanges.pressure.fuzz = 0;
1531 }
1532
1533 // Size factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001534 mLocked.sizeScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001535 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001536 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1537 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1538 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1539 }
1540 }
1541
1542 mLocked.orientedRanges.haveSize = true;
1543 mLocked.orientedRanges.size.min = 0;
1544 mLocked.orientedRanges.size.max = 1.0;
1545 mLocked.orientedRanges.size.flat = 0;
1546 mLocked.orientedRanges.size.fuzz = 0;
1547 }
1548
1549 // Orientation
Jeff Brown6b337e72010-10-14 21:42:15 -07001550 mLocked.orientationScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001551 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001552 if (mCalibration.orientationCalibration
1553 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1554 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1555 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1556 }
1557 }
1558
1559 mLocked.orientedRanges.orientation.min = - M_PI_2;
1560 mLocked.orientedRanges.orientation.max = M_PI_2;
1561 mLocked.orientedRanges.orientation.flat = 0;
1562 mLocked.orientedRanges.orientation.fuzz = 0;
1563 }
Jeff Browne57e8952010-07-23 21:28:06 -07001564 }
1565
1566 if (orientationChanged || sizeChanged) {
1567 // Compute oriented surface dimensions, precision, and scales.
1568 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001569 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001570 case InputReaderPolicyInterface::ROTATION_90:
1571 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001572 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1573 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1574 mLocked.orientedXPrecision = mLocked.yPrecision;
1575 mLocked.orientedYPrecision = mLocked.xPrecision;
1576 orientedXScale = mLocked.yScale;
1577 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001578 break;
1579 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001580 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1581 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1582 mLocked.orientedXPrecision = mLocked.xPrecision;
1583 mLocked.orientedYPrecision = mLocked.yPrecision;
1584 orientedXScale = mLocked.xScale;
1585 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001586 break;
1587 }
1588
1589 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001590 mLocked.orientedRanges.x.min = 0;
1591 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1592 mLocked.orientedRanges.x.flat = 0;
1593 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001594
Jeff Brownb51719b2010-07-29 18:18:33 -07001595 mLocked.orientedRanges.y.min = 0;
1596 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1597 mLocked.orientedRanges.y.flat = 0;
1598 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001599 }
1600
1601 return true;
1602}
1603
Jeff Brown26c94ff2010-09-30 14:33:04 -07001604void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1605 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1606 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1607 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Browna665ca82010-09-08 11:49:43 -07001608}
1609
Jeff Brownb51719b2010-07-29 18:18:33 -07001610void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001611 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001612
Jeff Brownb51719b2010-07-29 18:18:33 -07001613 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001614 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001615 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1616
Jeff Brownb51719b2010-07-29 18:18:33 -07001617 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001618
Jeff Brownb51719b2010-07-29 18:18:33 -07001619 if (virtualKeyDefinitions.size() == 0) {
1620 return;
1621 }
Jeff Browne57e8952010-07-23 21:28:06 -07001622
Jeff Brownb51719b2010-07-29 18:18:33 -07001623 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1624
Jeff Brown38a7fab2010-08-30 03:02:23 -07001625 int32_t touchScreenLeft = mRawAxes.x.minValue;
1626 int32_t touchScreenTop = mRawAxes.y.minValue;
1627 int32_t touchScreenWidth = mRawAxes.x.getRange();
1628 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001629
1630 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001631 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001632 virtualKeyDefinitions[i];
1633
1634 mLocked.virtualKeys.add();
1635 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1636
1637 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1638 int32_t keyCode;
1639 uint32_t flags;
1640 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1641 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001642 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1643 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001644 mLocked.virtualKeys.pop(); // drop the key
1645 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001646 }
1647
Jeff Brownb51719b2010-07-29 18:18:33 -07001648 virtualKey.keyCode = keyCode;
1649 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001650
Jeff Brownb51719b2010-07-29 18:18:33 -07001651 // convert the key definition's display coordinates into touch coordinates for a hit box
1652 int32_t halfWidth = virtualKeyDefinition.width / 2;
1653 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001654
Jeff Brownb51719b2010-07-29 18:18:33 -07001655 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1656 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1657 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1658 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1659 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1660 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1661 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1662 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001663
Jeff Brown26c94ff2010-09-30 14:33:04 -07001664 }
1665}
1666
1667void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1668 if (!mLocked.virtualKeys.isEmpty()) {
1669 dump.append(INDENT3 "Virtual Keys:\n");
1670
1671 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1672 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1673 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1674 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1675 i, virtualKey.scanCode, virtualKey.keyCode,
1676 virtualKey.hitLeft, virtualKey.hitRight,
1677 virtualKey.hitTop, virtualKey.hitBottom);
1678 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001679 }
Jeff Browne57e8952010-07-23 21:28:06 -07001680}
1681
Jeff Brown38a7fab2010-08-30 03:02:23 -07001682void TouchInputMapper::parseCalibration() {
1683 const InputDeviceCalibration& in = getDevice()->getCalibration();
1684 Calibration& out = mCalibration;
1685
Jeff Brown6b337e72010-10-14 21:42:15 -07001686 // Touch Size
1687 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1688 String8 touchSizeCalibrationString;
1689 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1690 if (touchSizeCalibrationString == "none") {
1691 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1692 } else if (touchSizeCalibrationString == "geometric") {
1693 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1694 } else if (touchSizeCalibrationString == "pressure") {
1695 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1696 } else if (touchSizeCalibrationString != "default") {
1697 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1698 touchSizeCalibrationString.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -07001699 }
1700 }
1701
Jeff Brown6b337e72010-10-14 21:42:15 -07001702 // Tool Size
1703 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1704 String8 toolSizeCalibrationString;
1705 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1706 if (toolSizeCalibrationString == "none") {
1707 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1708 } else if (toolSizeCalibrationString == "geometric") {
1709 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1710 } else if (toolSizeCalibrationString == "linear") {
1711 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1712 } else if (toolSizeCalibrationString == "area") {
1713 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1714 } else if (toolSizeCalibrationString != "default") {
1715 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1716 toolSizeCalibrationString.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -07001717 }
1718 }
1719
Jeff Brown6b337e72010-10-14 21:42:15 -07001720 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1721 out.toolSizeLinearScale);
1722 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1723 out.toolSizeLinearBias);
1724 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1725 out.toolSizeAreaScale);
1726 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1727 out.toolSizeAreaBias);
1728 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1729 out.toolSizeIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001730
1731 // Pressure
1732 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1733 String8 pressureCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001734 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001735 if (pressureCalibrationString == "none") {
1736 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1737 } else if (pressureCalibrationString == "physical") {
1738 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1739 } else if (pressureCalibrationString == "amplitude") {
1740 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1741 } else if (pressureCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001742 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001743 pressureCalibrationString.string());
1744 }
1745 }
1746
1747 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1748 String8 pressureSourceString;
1749 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1750 if (pressureSourceString == "pressure") {
1751 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1752 } else if (pressureSourceString == "touch") {
1753 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1754 } else if (pressureSourceString != "default") {
1755 LOGW("Invalid value for touch.pressure.source: '%s'",
1756 pressureSourceString.string());
1757 }
1758 }
1759
1760 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1761 out.pressureScale);
1762
1763 // Size
1764 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1765 String8 sizeCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001766 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001767 if (sizeCalibrationString == "none") {
1768 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1769 } else if (sizeCalibrationString == "normalized") {
1770 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1771 } else if (sizeCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001772 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001773 sizeCalibrationString.string());
1774 }
1775 }
1776
1777 // Orientation
1778 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1779 String8 orientationCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001780 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001781 if (orientationCalibrationString == "none") {
1782 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1783 } else if (orientationCalibrationString == "interpolated") {
1784 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1785 } else if (orientationCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001786 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001787 orientationCalibrationString.string());
1788 }
1789 }
1790}
1791
1792void TouchInputMapper::resolveCalibration() {
1793 // Pressure
1794 switch (mCalibration.pressureSource) {
1795 case Calibration::PRESSURE_SOURCE_DEFAULT:
1796 if (mRawAxes.pressure.valid) {
1797 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1798 } else if (mRawAxes.touchMajor.valid) {
1799 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1800 }
1801 break;
1802
1803 case Calibration::PRESSURE_SOURCE_PRESSURE:
1804 if (! mRawAxes.pressure.valid) {
1805 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1806 "the pressure axis is not available.");
1807 }
1808 break;
1809
1810 case Calibration::PRESSURE_SOURCE_TOUCH:
1811 if (! mRawAxes.touchMajor.valid) {
1812 LOGW("Calibration property touch.pressure.source is 'touch' but "
1813 "the touchMajor axis is not available.");
1814 }
1815 break;
1816
1817 default:
1818 break;
1819 }
1820
1821 switch (mCalibration.pressureCalibration) {
1822 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1823 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1824 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1825 } else {
1826 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1827 }
1828 break;
1829
1830 default:
1831 break;
1832 }
1833
Jeff Brown6b337e72010-10-14 21:42:15 -07001834 // Tool Size
1835 switch (mCalibration.toolSizeCalibration) {
1836 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown38a7fab2010-08-30 03:02:23 -07001837 if (mRawAxes.toolMajor.valid) {
Jeff Brown6b337e72010-10-14 21:42:15 -07001838 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001839 } else {
Jeff Brown6b337e72010-10-14 21:42:15 -07001840 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001841 }
1842 break;
1843
1844 default:
1845 break;
1846 }
1847
Jeff Brown6b337e72010-10-14 21:42:15 -07001848 // Touch Size
1849 switch (mCalibration.touchSizeCalibration) {
1850 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown38a7fab2010-08-30 03:02:23 -07001851 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brown6b337e72010-10-14 21:42:15 -07001852 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1853 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001854 } else {
Jeff Brown6b337e72010-10-14 21:42:15 -07001855 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001856 }
1857 break;
1858
1859 default:
1860 break;
1861 }
1862
1863 // Size
1864 switch (mCalibration.sizeCalibration) {
1865 case Calibration::SIZE_CALIBRATION_DEFAULT:
1866 if (mRawAxes.toolMajor.valid) {
1867 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1868 } else {
1869 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1870 }
1871 break;
1872
1873 default:
1874 break;
1875 }
1876
1877 // Orientation
1878 switch (mCalibration.orientationCalibration) {
1879 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1880 if (mRawAxes.orientation.valid) {
1881 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1882 } else {
1883 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1884 }
1885 break;
1886
1887 default:
1888 break;
1889 }
1890}
1891
Jeff Brown26c94ff2010-09-30 14:33:04 -07001892void TouchInputMapper::dumpCalibration(String8& dump) {
1893 dump.append(INDENT3 "Calibration:\n");
Jeff Browna665ca82010-09-08 11:49:43 -07001894
Jeff Brown6b337e72010-10-14 21:42:15 -07001895 // Touch Size
1896 switch (mCalibration.touchSizeCalibration) {
1897 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
1898 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001899 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001900 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
1901 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001902 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001903 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
1904 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001905 break;
1906 default:
1907 assert(false);
1908 }
1909
Jeff Brown6b337e72010-10-14 21:42:15 -07001910 // Tool Size
1911 switch (mCalibration.toolSizeCalibration) {
1912 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
1913 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001914 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001915 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
1916 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001917 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001918 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
1919 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
1920 break;
1921 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
1922 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001923 break;
1924 default:
1925 assert(false);
1926 }
1927
Jeff Brown6b337e72010-10-14 21:42:15 -07001928 if (mCalibration.haveToolSizeLinearScale) {
1929 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
1930 mCalibration.toolSizeLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001931 }
1932
Jeff Brown6b337e72010-10-14 21:42:15 -07001933 if (mCalibration.haveToolSizeLinearBias) {
1934 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
1935 mCalibration.toolSizeLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001936 }
1937
Jeff Brown6b337e72010-10-14 21:42:15 -07001938 if (mCalibration.haveToolSizeAreaScale) {
1939 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
1940 mCalibration.toolSizeAreaScale);
1941 }
1942
1943 if (mCalibration.haveToolSizeAreaBias) {
1944 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
1945 mCalibration.toolSizeAreaBias);
1946 }
1947
1948 if (mCalibration.haveToolSizeIsSummed) {
1949 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %d\n",
1950 mCalibration.toolSizeIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001951 }
1952
1953 // Pressure
1954 switch (mCalibration.pressureCalibration) {
1955 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001956 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001957 break;
1958 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001959 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001960 break;
1961 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001962 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001963 break;
1964 default:
1965 assert(false);
1966 }
1967
1968 switch (mCalibration.pressureSource) {
1969 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001970 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001971 break;
1972 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001973 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001974 break;
1975 case Calibration::PRESSURE_SOURCE_DEFAULT:
1976 break;
1977 default:
1978 assert(false);
1979 }
1980
1981 if (mCalibration.havePressureScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001982 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
1983 mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001984 }
1985
1986 // Size
1987 switch (mCalibration.sizeCalibration) {
1988 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001989 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001990 break;
1991 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001992 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001993 break;
1994 default:
1995 assert(false);
1996 }
1997
1998 // Orientation
1999 switch (mCalibration.orientationCalibration) {
2000 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002001 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002002 break;
2003 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002004 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002005 break;
2006 default:
2007 assert(false);
2008 }
2009}
2010
Jeff Browne57e8952010-07-23 21:28:06 -07002011void TouchInputMapper::reset() {
2012 // Synthesize touch up event if touch is currently down.
2013 // This will also take care of finishing virtual key processing if needed.
2014 if (mLastTouch.pointerCount != 0) {
2015 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2016 mCurrentTouch.clear();
2017 syncTouch(when, true);
2018 }
2019
Jeff Brownb51719b2010-07-29 18:18:33 -07002020 { // acquire lock
2021 AutoMutex _l(mLock);
2022 initializeLocked();
2023 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002024
Jeff Brownb51719b2010-07-29 18:18:33 -07002025 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07002026}
2027
2028void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Browne839a582010-04-22 18:58:52 -07002029 uint32_t policyFlags = 0;
Jeff Browne839a582010-04-22 18:58:52 -07002030
Jeff Brownb51719b2010-07-29 18:18:33 -07002031 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07002032
Jeff Browne57e8952010-07-23 21:28:06 -07002033 if (mParameters.useBadTouchFilter) {
2034 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002035 havePointerIds = false;
2036 }
2037 }
2038
Jeff Browne57e8952010-07-23 21:28:06 -07002039 if (mParameters.useJumpyTouchFilter) {
2040 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002041 havePointerIds = false;
2042 }
2043 }
2044
2045 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002046 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002047 }
2048
Jeff Browne57e8952010-07-23 21:28:06 -07002049 TouchData temp;
2050 TouchData* savedTouch;
2051 if (mParameters.useAveragingTouchFilter) {
2052 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002053 savedTouch = & temp;
2054
Jeff Browne57e8952010-07-23 21:28:06 -07002055 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002056 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002057 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002058 }
2059
Jeff Brownb51719b2010-07-29 18:18:33 -07002060 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002061
Jeff Browne57e8952010-07-23 21:28:06 -07002062 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2063 if (touchResult == DISPATCH_TOUCH) {
2064 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002065 }
2066
Jeff Brownb51719b2010-07-29 18:18:33 -07002067 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002068
Jeff Browne57e8952010-07-23 21:28:06 -07002069 if (touchResult == DROP_STROKE) {
2070 mLastTouch.clear();
2071 } else {
2072 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002073 }
Jeff Browne839a582010-04-22 18:58:52 -07002074}
2075
Jeff Browne57e8952010-07-23 21:28:06 -07002076TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2077 nsecs_t when, uint32_t policyFlags) {
2078 int32_t keyEventAction, keyEventFlags;
2079 int32_t keyCode, scanCode, downTime;
2080 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002081
Jeff Brownb51719b2010-07-29 18:18:33 -07002082 { // acquire lock
2083 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002084
Jeff Brownb51719b2010-07-29 18:18:33 -07002085 // Update surface size and orientation, including virtual key positions.
2086 if (! configureSurfaceLocked()) {
2087 return DROP_STROKE;
2088 }
2089
2090 // Check for virtual key press.
2091 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002092 if (mCurrentTouch.pointerCount == 0) {
2093 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002094 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002095#if DEBUG_VIRTUAL_KEYS
2096 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2097 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2098#endif
2099 keyEventAction = AKEY_EVENT_ACTION_UP;
2100 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2101 touchResult = SKIP_TOUCH;
2102 goto DispatchVirtualKey;
2103 }
2104
2105 if (mCurrentTouch.pointerCount == 1) {
2106 int32_t x = mCurrentTouch.pointers[0].x;
2107 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002108 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2109 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002110 // Pointer is still within the space of the virtual key.
2111 return SKIP_TOUCH;
2112 }
2113 }
2114
2115 // Pointer left virtual key area or another pointer also went down.
2116 // Send key cancellation and drop the stroke so subsequent motions will be
2117 // considered fresh downs. This is useful when the user swipes away from the
2118 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002119 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002120#if DEBUG_VIRTUAL_KEYS
2121 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2122 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2123#endif
2124 keyEventAction = AKEY_EVENT_ACTION_UP;
2125 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2126 | AKEY_EVENT_FLAG_CANCELED;
2127 touchResult = DROP_STROKE;
2128 goto DispatchVirtualKey;
2129 } else {
2130 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2131 // Pointer just went down. Handle off-screen touches, if needed.
2132 int32_t x = mCurrentTouch.pointers[0].x;
2133 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002134 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002135 // If exactly one pointer went down, check for virtual key hit.
2136 // Otherwise we will drop the entire stroke.
2137 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002138 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002139 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002140 mLocked.currentVirtualKey.down = true;
2141 mLocked.currentVirtualKey.downTime = when;
2142 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2143 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002144#if DEBUG_VIRTUAL_KEYS
2145 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2146 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2147#endif
2148 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2149 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2150 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2151 touchResult = SKIP_TOUCH;
2152 goto DispatchVirtualKey;
2153 }
2154 }
2155 return DROP_STROKE;
2156 }
2157 }
2158 return DISPATCH_TOUCH;
2159 }
2160
2161 DispatchVirtualKey:
2162 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002163 keyCode = mLocked.currentVirtualKey.keyCode;
2164 scanCode = mLocked.currentVirtualKey.scanCode;
2165 downTime = mLocked.currentVirtualKey.downTime;
2166 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002167
2168 // Dispatch virtual key.
2169 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown956c0fb2010-10-01 14:55:30 -07002170 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brown90f0cee2010-10-08 22:31:17 -07002171 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2172 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2173 return touchResult;
Jeff Browne839a582010-04-22 18:58:52 -07002174}
2175
Jeff Browne57e8952010-07-23 21:28:06 -07002176void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2177 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2178 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002179 if (currentPointerCount == 0 && lastPointerCount == 0) {
2180 return; // nothing to do!
2181 }
2182
Jeff Browne57e8952010-07-23 21:28:06 -07002183 BitSet32 currentIdBits = mCurrentTouch.idBits;
2184 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002185
2186 if (currentIdBits == lastIdBits) {
2187 // No pointer id changes so this is a move event.
2188 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002189 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002190 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002191 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002192 } else {
2193 // There may be pointers going up and pointers going down at the same time when pointer
2194 // ids are reported by the device driver.
2195 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2196 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2197 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002198 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002199
2200 while (! upIdBits.isEmpty()) {
2201 uint32_t upId = upIdBits.firstMarkedBit();
2202 upIdBits.clearBit(upId);
2203 BitSet32 oldActiveIdBits = activeIdBits;
2204 activeIdBits.clearBit(upId);
2205
2206 int32_t motionEventAction;
2207 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002208 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002209 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002210 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002211 }
2212
Jeff Browne57e8952010-07-23 21:28:06 -07002213 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002214 oldActiveIdBits, upId, pointerCount, motionEventAction);
2215 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002216 }
2217
2218 while (! downIdBits.isEmpty()) {
2219 uint32_t downId = downIdBits.firstMarkedBit();
2220 downIdBits.clearBit(downId);
2221 BitSet32 oldActiveIdBits = activeIdBits;
2222 activeIdBits.markBit(downId);
2223
2224 int32_t motionEventAction;
2225 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002226 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002227 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002228 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002229 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002230 }
2231
Jeff Brown38a7fab2010-08-30 03:02:23 -07002232 pointerCount += 1;
Jeff Browne57e8952010-07-23 21:28:06 -07002233 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002234 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002235 }
2236 }
2237}
2238
Jeff Browne57e8952010-07-23 21:28:06 -07002239void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002240 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002241 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002242 int32_t pointerIds[MAX_POINTERS];
2243 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002244 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002245 float xPrecision, yPrecision;
2246
2247 { // acquire lock
2248 AutoMutex _l(mLock);
2249
2250 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2251 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002252 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002253 uint32_t id = idBits.firstMarkedBit();
2254 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002255 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002256
Jeff Brown38a7fab2010-08-30 03:02:23 -07002257 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002258
Jeff Brown38a7fab2010-08-30 03:02:23 -07002259 // X and Y
2260 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2261 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002262
Jeff Brown38a7fab2010-08-30 03:02:23 -07002263 // ToolMajor and ToolMinor
2264 float toolMajor, toolMinor;
Jeff Brown6b337e72010-10-14 21:42:15 -07002265 switch (mCalibration.toolSizeCalibration) {
2266 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002267 toolMajor = in.toolMajor * mLocked.geometricScale;
2268 if (mRawAxes.toolMinor.valid) {
2269 toolMinor = in.toolMinor * mLocked.geometricScale;
2270 } else {
2271 toolMinor = toolMajor;
2272 }
2273 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002274 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002275 toolMajor = in.toolMajor != 0
Jeff Brown6b337e72010-10-14 21:42:15 -07002276 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown38a7fab2010-08-30 03:02:23 -07002277 : 0;
2278 if (mRawAxes.toolMinor.valid) {
2279 toolMinor = in.toolMinor != 0
Jeff Brown6b337e72010-10-14 21:42:15 -07002280 ? in.toolMinor * mLocked.toolSizeLinearScale
2281 + mLocked.toolSizeLinearBias
Jeff Brown38a7fab2010-08-30 03:02:23 -07002282 : 0;
2283 } else {
2284 toolMinor = toolMajor;
2285 }
2286 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002287 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2288 if (in.toolMajor != 0) {
2289 float diameter = sqrtf(in.toolMajor
2290 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2291 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2292 } else {
2293 toolMajor = 0;
2294 }
2295 toolMinor = toolMajor;
2296 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002297 default:
2298 toolMajor = 0;
2299 toolMinor = 0;
2300 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002301 }
2302
Jeff Brown6b337e72010-10-14 21:42:15 -07002303 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002304 toolMajor /= pointerCount;
2305 toolMinor /= pointerCount;
2306 }
2307
2308 // Pressure
2309 float rawPressure;
2310 switch (mCalibration.pressureSource) {
2311 case Calibration::PRESSURE_SOURCE_PRESSURE:
2312 rawPressure = in.pressure;
2313 break;
2314 case Calibration::PRESSURE_SOURCE_TOUCH:
2315 rawPressure = in.touchMajor;
2316 break;
2317 default:
2318 rawPressure = 0;
2319 }
2320
2321 float pressure;
2322 switch (mCalibration.pressureCalibration) {
2323 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2324 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2325 pressure = rawPressure * mLocked.pressureScale;
2326 break;
2327 default:
2328 pressure = 1;
2329 break;
2330 }
2331
2332 // TouchMajor and TouchMinor
2333 float touchMajor, touchMinor;
Jeff Brown6b337e72010-10-14 21:42:15 -07002334 switch (mCalibration.touchSizeCalibration) {
2335 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002336 touchMajor = in.touchMajor * mLocked.geometricScale;
2337 if (mRawAxes.touchMinor.valid) {
2338 touchMinor = in.touchMinor * mLocked.geometricScale;
2339 } else {
2340 touchMinor = touchMajor;
2341 }
2342 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002343 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002344 touchMajor = toolMajor * pressure;
2345 touchMinor = toolMinor * pressure;
2346 break;
2347 default:
2348 touchMajor = 0;
2349 touchMinor = 0;
2350 break;
2351 }
2352
2353 if (touchMajor > toolMajor) {
2354 touchMajor = toolMajor;
2355 }
2356 if (touchMinor > toolMinor) {
2357 touchMinor = toolMinor;
2358 }
2359
2360 // Size
2361 float size;
2362 switch (mCalibration.sizeCalibration) {
2363 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2364 float rawSize = mRawAxes.toolMinor.valid
2365 ? avg(in.toolMajor, in.toolMinor)
2366 : in.toolMajor;
2367 size = rawSize * mLocked.sizeScale;
2368 break;
2369 }
2370 default:
2371 size = 0;
2372 break;
2373 }
2374
2375 // Orientation
2376 float orientation;
2377 switch (mCalibration.orientationCalibration) {
2378 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2379 orientation = in.orientation * mLocked.orientationScale;
2380 break;
2381 default:
2382 orientation = 0;
2383 }
2384
2385 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002386 switch (mLocked.surfaceOrientation) {
2387 case InputReaderPolicyInterface::ROTATION_90: {
2388 float xTemp = x;
2389 x = y;
2390 y = mLocked.surfaceWidth - xTemp;
2391 orientation -= M_PI_2;
2392 if (orientation < - M_PI_2) {
2393 orientation += M_PI;
2394 }
2395 break;
2396 }
2397 case InputReaderPolicyInterface::ROTATION_180: {
2398 x = mLocked.surfaceWidth - x;
2399 y = mLocked.surfaceHeight - y;
2400 orientation = - orientation;
2401 break;
2402 }
2403 case InputReaderPolicyInterface::ROTATION_270: {
2404 float xTemp = x;
2405 x = mLocked.surfaceHeight - y;
2406 y = xTemp;
2407 orientation += M_PI_2;
2408 if (orientation > M_PI_2) {
2409 orientation -= M_PI;
2410 }
2411 break;
2412 }
2413 }
2414
Jeff Brown38a7fab2010-08-30 03:02:23 -07002415 // Write output coords.
2416 PointerCoords& out = pointerCoords[outIndex];
2417 out.x = x;
2418 out.y = y;
2419 out.pressure = pressure;
2420 out.size = size;
2421 out.touchMajor = touchMajor;
2422 out.touchMinor = touchMinor;
2423 out.toolMajor = toolMajor;
2424 out.toolMinor = toolMinor;
2425 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002426
Jeff Brown38a7fab2010-08-30 03:02:23 -07002427 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002428
2429 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002430 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002431 }
Jeff Browne839a582010-04-22 18:58:52 -07002432 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002433
2434 // Check edge flags by looking only at the first pointer since the flags are
2435 // global to the event.
2436 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2437 if (pointerCoords[0].x <= 0) {
2438 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2439 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2440 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2441 }
2442 if (pointerCoords[0].y <= 0) {
2443 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2444 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2445 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2446 }
Jeff Browne839a582010-04-22 18:58:52 -07002447 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002448
2449 xPrecision = mLocked.orientedXPrecision;
2450 yPrecision = mLocked.orientedYPrecision;
2451 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002452
Jeff Brown77e26fc2010-10-07 13:44:51 -07002453 getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002454 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002455 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002456 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002457}
2458
Jeff Brownb51719b2010-07-29 18:18:33 -07002459bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002460 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2461 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2462 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002463 }
Jeff Browne57e8952010-07-23 21:28:06 -07002464 return true;
2465}
2466
Jeff Brownb51719b2010-07-29 18:18:33 -07002467const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2468 int32_t x, int32_t y) {
2469 size_t numVirtualKeys = mLocked.virtualKeys.size();
2470 for (size_t i = 0; i < numVirtualKeys; i++) {
2471 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002472
2473#if DEBUG_VIRTUAL_KEYS
2474 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2475 "left=%d, top=%d, right=%d, bottom=%d",
2476 x, y,
2477 virtualKey.keyCode, virtualKey.scanCode,
2478 virtualKey.hitLeft, virtualKey.hitTop,
2479 virtualKey.hitRight, virtualKey.hitBottom);
2480#endif
2481
2482 if (virtualKey.isHit(x, y)) {
2483 return & virtualKey;
2484 }
2485 }
2486
2487 return NULL;
2488}
2489
2490void TouchInputMapper::calculatePointerIds() {
2491 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2492 uint32_t lastPointerCount = mLastTouch.pointerCount;
2493
2494 if (currentPointerCount == 0) {
2495 // No pointers to assign.
2496 mCurrentTouch.idBits.clear();
2497 } else if (lastPointerCount == 0) {
2498 // All pointers are new.
2499 mCurrentTouch.idBits.clear();
2500 for (uint32_t i = 0; i < currentPointerCount; i++) {
2501 mCurrentTouch.pointers[i].id = i;
2502 mCurrentTouch.idToIndex[i] = i;
2503 mCurrentTouch.idBits.markBit(i);
2504 }
2505 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2506 // Only one pointer and no change in count so it must have the same id as before.
2507 uint32_t id = mLastTouch.pointers[0].id;
2508 mCurrentTouch.pointers[0].id = id;
2509 mCurrentTouch.idToIndex[id] = 0;
2510 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2511 } else {
2512 // General case.
2513 // We build a heap of squared euclidean distances between current and last pointers
2514 // associated with the current and last pointer indices. Then, we find the best
2515 // match (by distance) for each current pointer.
2516 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2517
2518 uint32_t heapSize = 0;
2519 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2520 currentPointerIndex++) {
2521 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2522 lastPointerIndex++) {
2523 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2524 - mLastTouch.pointers[lastPointerIndex].x;
2525 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2526 - mLastTouch.pointers[lastPointerIndex].y;
2527
2528 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2529
2530 // Insert new element into the heap (sift up).
2531 heap[heapSize].currentPointerIndex = currentPointerIndex;
2532 heap[heapSize].lastPointerIndex = lastPointerIndex;
2533 heap[heapSize].distance = distance;
2534 heapSize += 1;
2535 }
2536 }
2537
2538 // Heapify
2539 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2540 startIndex -= 1;
2541 for (uint32_t parentIndex = startIndex; ;) {
2542 uint32_t childIndex = parentIndex * 2 + 1;
2543 if (childIndex >= heapSize) {
2544 break;
2545 }
2546
2547 if (childIndex + 1 < heapSize
2548 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2549 childIndex += 1;
2550 }
2551
2552 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2553 break;
2554 }
2555
2556 swap(heap[parentIndex], heap[childIndex]);
2557 parentIndex = childIndex;
2558 }
2559 }
2560
2561#if DEBUG_POINTER_ASSIGNMENT
2562 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2563 for (size_t i = 0; i < heapSize; i++) {
2564 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2565 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2566 heap[i].distance);
2567 }
2568#endif
2569
2570 // Pull matches out by increasing order of distance.
2571 // To avoid reassigning pointers that have already been matched, the loop keeps track
2572 // of which last and current pointers have been matched using the matchedXXXBits variables.
2573 // It also tracks the used pointer id bits.
2574 BitSet32 matchedLastBits(0);
2575 BitSet32 matchedCurrentBits(0);
2576 BitSet32 usedIdBits(0);
2577 bool first = true;
2578 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2579 for (;;) {
2580 if (first) {
2581 // The first time through the loop, we just consume the root element of
2582 // the heap (the one with smallest distance).
2583 first = false;
2584 } else {
2585 // Previous iterations consumed the root element of the heap.
2586 // Pop root element off of the heap (sift down).
2587 heapSize -= 1;
2588 assert(heapSize > 0);
2589
2590 // Sift down.
2591 heap[0] = heap[heapSize];
2592 for (uint32_t parentIndex = 0; ;) {
2593 uint32_t childIndex = parentIndex * 2 + 1;
2594 if (childIndex >= heapSize) {
2595 break;
2596 }
2597
2598 if (childIndex + 1 < heapSize
2599 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2600 childIndex += 1;
2601 }
2602
2603 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2604 break;
2605 }
2606
2607 swap(heap[parentIndex], heap[childIndex]);
2608 parentIndex = childIndex;
2609 }
2610
2611#if DEBUG_POINTER_ASSIGNMENT
2612 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2613 for (size_t i = 0; i < heapSize; i++) {
2614 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2615 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2616 heap[i].distance);
2617 }
2618#endif
2619 }
2620
2621 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2622 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2623
2624 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2625 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2626
2627 matchedCurrentBits.markBit(currentPointerIndex);
2628 matchedLastBits.markBit(lastPointerIndex);
2629
2630 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2631 mCurrentTouch.pointers[currentPointerIndex].id = id;
2632 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2633 usedIdBits.markBit(id);
2634
2635#if DEBUG_POINTER_ASSIGNMENT
2636 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2637 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2638#endif
2639 break;
2640 }
2641 }
2642
2643 // Assign fresh ids to new pointers.
2644 if (currentPointerCount > lastPointerCount) {
2645 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2646 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2647 uint32_t id = usedIdBits.firstUnmarkedBit();
2648
2649 mCurrentTouch.pointers[currentPointerIndex].id = id;
2650 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2651 usedIdBits.markBit(id);
2652
2653#if DEBUG_POINTER_ASSIGNMENT
2654 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2655 currentPointerIndex, id);
2656#endif
2657
2658 if (--i == 0) break; // done
2659 matchedCurrentBits.markBit(currentPointerIndex);
2660 }
2661 }
2662
2663 // Fix id bits.
2664 mCurrentTouch.idBits = usedIdBits;
2665 }
2666}
2667
2668/* Special hack for devices that have bad screen data: if one of the
2669 * points has moved more than a screen height from the last position,
2670 * then drop it. */
2671bool TouchInputMapper::applyBadTouchFilter() {
2672 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002673 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002674 return false;
2675 }
2676
2677 uint32_t pointerCount = mCurrentTouch.pointerCount;
2678
2679 // Nothing to do if there are no points.
2680 if (pointerCount == 0) {
2681 return false;
2682 }
2683
2684 // Don't do anything if a finger is going down or up. We run
2685 // here before assigning pointer IDs, so there isn't a good
2686 // way to do per-finger matching.
2687 if (pointerCount != mLastTouch.pointerCount) {
2688 return false;
2689 }
2690
2691 // We consider a single movement across more than a 7/16 of
2692 // the long size of the screen to be bad. This was a magic value
2693 // determined by looking at the maximum distance it is feasible
2694 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002695 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002696
2697 // XXX The original code in InputDevice.java included commented out
2698 // code for testing the X axis. Note that when we drop a point
2699 // we don't actually restore the old X either. Strange.
2700 // The old code also tries to track when bad points were previously
2701 // detected but it turns out that due to the placement of a "break"
2702 // at the end of the loop, we never set mDroppedBadPoint to true
2703 // so it is effectively dead code.
2704 // Need to figure out if the old code is busted or just overcomplicated
2705 // but working as intended.
2706
2707 // Look through all new points and see if any are farther than
2708 // acceptable from all previous points.
2709 for (uint32_t i = pointerCount; i-- > 0; ) {
2710 int32_t y = mCurrentTouch.pointers[i].y;
2711 int32_t closestY = INT_MAX;
2712 int32_t closestDeltaY = 0;
2713
2714#if DEBUG_HACKS
2715 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2716#endif
2717
2718 for (uint32_t j = pointerCount; j-- > 0; ) {
2719 int32_t lastY = mLastTouch.pointers[j].y;
2720 int32_t deltaY = abs(y - lastY);
2721
2722#if DEBUG_HACKS
2723 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2724 j, lastY, deltaY);
2725#endif
2726
2727 if (deltaY < maxDeltaY) {
2728 goto SkipSufficientlyClosePoint;
2729 }
2730 if (deltaY < closestDeltaY) {
2731 closestDeltaY = deltaY;
2732 closestY = lastY;
2733 }
2734 }
2735
2736 // Must not have found a close enough match.
2737#if DEBUG_HACKS
2738 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2739 i, y, closestY, closestDeltaY, maxDeltaY);
2740#endif
2741
2742 mCurrentTouch.pointers[i].y = closestY;
2743 return true; // XXX original code only corrects one point
2744
2745 SkipSufficientlyClosePoint: ;
2746 }
2747
2748 // No change.
2749 return false;
2750}
2751
2752/* Special hack for devices that have bad screen data: drop points where
2753 * the coordinate value for one axis has jumped to the other pointer's location.
2754 */
2755bool TouchInputMapper::applyJumpyTouchFilter() {
2756 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002757 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002758 return false;
2759 }
2760
2761 uint32_t pointerCount = mCurrentTouch.pointerCount;
2762 if (mLastTouch.pointerCount != pointerCount) {
2763#if DEBUG_HACKS
2764 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2765 mLastTouch.pointerCount, pointerCount);
2766 for (uint32_t i = 0; i < pointerCount; i++) {
2767 LOGD(" Pointer %d (%d, %d)", i,
2768 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2769 }
2770#endif
2771
2772 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2773 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2774 // Just drop the first few events going from 1 to 2 pointers.
2775 // They're bad often enough that they're not worth considering.
2776 mCurrentTouch.pointerCount = 1;
2777 mJumpyTouchFilter.jumpyPointsDropped += 1;
2778
2779#if DEBUG_HACKS
2780 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2781#endif
2782 return true;
2783 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2784 // The event when we go from 2 -> 1 tends to be messed up too
2785 mCurrentTouch.pointerCount = 2;
2786 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2787 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2788 mJumpyTouchFilter.jumpyPointsDropped += 1;
2789
2790#if DEBUG_HACKS
2791 for (int32_t i = 0; i < 2; i++) {
2792 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2793 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2794 }
2795#endif
2796 return true;
2797 }
2798 }
2799 // Reset jumpy points dropped on other transitions or if limit exceeded.
2800 mJumpyTouchFilter.jumpyPointsDropped = 0;
2801
2802#if DEBUG_HACKS
2803 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2804#endif
2805 return false;
2806 }
2807
2808 // We have the same number of pointers as last time.
2809 // A 'jumpy' point is one where the coordinate value for one axis
2810 // has jumped to the other pointer's location. No need to do anything
2811 // else if we only have one pointer.
2812 if (pointerCount < 2) {
2813 return false;
2814 }
2815
2816 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002817 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002818
2819 // We only replace the single worst jumpy point as characterized by pointer distance
2820 // in a single axis.
2821 int32_t badPointerIndex = -1;
2822 int32_t badPointerReplacementIndex = -1;
2823 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2824
2825 for (uint32_t i = pointerCount; i-- > 0; ) {
2826 int32_t x = mCurrentTouch.pointers[i].x;
2827 int32_t y = mCurrentTouch.pointers[i].y;
2828
2829#if DEBUG_HACKS
2830 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2831#endif
2832
2833 // Check if a touch point is too close to another's coordinates
2834 bool dropX = false, dropY = false;
2835 for (uint32_t j = 0; j < pointerCount; j++) {
2836 if (i == j) {
2837 continue;
2838 }
2839
2840 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2841 dropX = true;
2842 break;
2843 }
2844
2845 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2846 dropY = true;
2847 break;
2848 }
2849 }
2850 if (! dropX && ! dropY) {
2851 continue; // not jumpy
2852 }
2853
2854 // Find a replacement candidate by comparing with older points on the
2855 // complementary (non-jumpy) axis.
2856 int32_t distance = INT_MIN; // distance to be corrected
2857 int32_t replacementIndex = -1;
2858
2859 if (dropX) {
2860 // X looks too close. Find an older replacement point with a close Y.
2861 int32_t smallestDeltaY = INT_MAX;
2862 for (uint32_t j = 0; j < pointerCount; j++) {
2863 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2864 if (deltaY < smallestDeltaY) {
2865 smallestDeltaY = deltaY;
2866 replacementIndex = j;
2867 }
2868 }
2869 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2870 } else {
2871 // Y looks too close. Find an older replacement point with a close X.
2872 int32_t smallestDeltaX = INT_MAX;
2873 for (uint32_t j = 0; j < pointerCount; j++) {
2874 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2875 if (deltaX < smallestDeltaX) {
2876 smallestDeltaX = deltaX;
2877 replacementIndex = j;
2878 }
2879 }
2880 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2881 }
2882
2883 // If replacing this pointer would correct a worse error than the previous ones
2884 // considered, then use this replacement instead.
2885 if (distance > badPointerDistance) {
2886 badPointerIndex = i;
2887 badPointerReplacementIndex = replacementIndex;
2888 badPointerDistance = distance;
2889 }
2890 }
2891
2892 // Correct the jumpy pointer if one was found.
2893 if (badPointerIndex >= 0) {
2894#if DEBUG_HACKS
2895 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2896 badPointerIndex,
2897 mLastTouch.pointers[badPointerReplacementIndex].x,
2898 mLastTouch.pointers[badPointerReplacementIndex].y);
2899#endif
2900
2901 mCurrentTouch.pointers[badPointerIndex].x =
2902 mLastTouch.pointers[badPointerReplacementIndex].x;
2903 mCurrentTouch.pointers[badPointerIndex].y =
2904 mLastTouch.pointers[badPointerReplacementIndex].y;
2905 mJumpyTouchFilter.jumpyPointsDropped += 1;
2906 return true;
2907 }
2908 }
2909
2910 mJumpyTouchFilter.jumpyPointsDropped = 0;
2911 return false;
2912}
2913
2914/* Special hack for devices that have bad screen data: aggregate and
2915 * compute averages of the coordinate data, to reduce the amount of
2916 * jitter seen by applications. */
2917void TouchInputMapper::applyAveragingTouchFilter() {
2918 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2919 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2920 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2921 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002922 int32_t pressure;
2923 switch (mCalibration.pressureSource) {
2924 case Calibration::PRESSURE_SOURCE_PRESSURE:
2925 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2926 break;
2927 case Calibration::PRESSURE_SOURCE_TOUCH:
2928 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2929 break;
2930 default:
2931 pressure = 1;
2932 break;
2933 }
Jeff Browne57e8952010-07-23 21:28:06 -07002934
2935 if (mLastTouch.idBits.hasBit(id)) {
2936 // Pointer was down before and is still down now.
2937 // Compute average over history trace.
2938 uint32_t start = mAveragingTouchFilter.historyStart[id];
2939 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2940
2941 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2942 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2943 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2944
2945#if DEBUG_HACKS
2946 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2947 id, distance);
2948#endif
2949
2950 if (distance < AVERAGING_DISTANCE_LIMIT) {
2951 // Increment end index in preparation for recording new historical data.
2952 end += 1;
2953 if (end > AVERAGING_HISTORY_SIZE) {
2954 end = 0;
2955 }
2956
2957 // If the end index has looped back to the start index then we have filled
2958 // the historical trace up to the desired size so we drop the historical
2959 // data at the start of the trace.
2960 if (end == start) {
2961 start += 1;
2962 if (start > AVERAGING_HISTORY_SIZE) {
2963 start = 0;
2964 }
2965 }
2966
2967 // Add the raw data to the historical trace.
2968 mAveragingTouchFilter.historyStart[id] = start;
2969 mAveragingTouchFilter.historyEnd[id] = end;
2970 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2971 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2972 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2973
2974 // Average over all historical positions in the trace by total pressure.
2975 int32_t averagedX = 0;
2976 int32_t averagedY = 0;
2977 int32_t totalPressure = 0;
2978 for (;;) {
2979 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2980 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2981 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2982 .pointers[id].pressure;
2983
2984 averagedX += historicalX * historicalPressure;
2985 averagedY += historicalY * historicalPressure;
2986 totalPressure += historicalPressure;
2987
2988 if (start == end) {
2989 break;
2990 }
2991
2992 start += 1;
2993 if (start > AVERAGING_HISTORY_SIZE) {
2994 start = 0;
2995 }
2996 }
2997
Jeff Brown38a7fab2010-08-30 03:02:23 -07002998 if (totalPressure != 0) {
2999 averagedX /= totalPressure;
3000 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07003001
3002#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07003003 LOGD("AveragingTouchFilter: Pointer id %d - "
3004 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3005 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07003006#endif
3007
Jeff Brown38a7fab2010-08-30 03:02:23 -07003008 mCurrentTouch.pointers[currentIndex].x = averagedX;
3009 mCurrentTouch.pointers[currentIndex].y = averagedY;
3010 }
Jeff Browne57e8952010-07-23 21:28:06 -07003011 } else {
3012#if DEBUG_HACKS
3013 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3014#endif
3015 }
3016 } else {
3017#if DEBUG_HACKS
3018 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3019#endif
3020 }
3021
3022 // Reset pointer history.
3023 mAveragingTouchFilter.historyStart[id] = 0;
3024 mAveragingTouchFilter.historyEnd[id] = 0;
3025 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3026 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3027 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3028 }
3029}
3030
3031int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003032 { // acquire lock
3033 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003034
Jeff Brownb51719b2010-07-29 18:18:33 -07003035 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003036 return AKEY_STATE_VIRTUAL;
3037 }
3038
Jeff Brownb51719b2010-07-29 18:18:33 -07003039 size_t numVirtualKeys = mLocked.virtualKeys.size();
3040 for (size_t i = 0; i < numVirtualKeys; i++) {
3041 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003042 if (virtualKey.keyCode == keyCode) {
3043 return AKEY_STATE_UP;
3044 }
3045 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003046 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003047
3048 return AKEY_STATE_UNKNOWN;
3049}
3050
3051int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003052 { // acquire lock
3053 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003054
Jeff Brownb51719b2010-07-29 18:18:33 -07003055 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003056 return AKEY_STATE_VIRTUAL;
3057 }
3058
Jeff Brownb51719b2010-07-29 18:18:33 -07003059 size_t numVirtualKeys = mLocked.virtualKeys.size();
3060 for (size_t i = 0; i < numVirtualKeys; i++) {
3061 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003062 if (virtualKey.scanCode == scanCode) {
3063 return AKEY_STATE_UP;
3064 }
3065 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003066 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003067
3068 return AKEY_STATE_UNKNOWN;
3069}
3070
3071bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3072 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003073 { // acquire lock
3074 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003075
Jeff Brownb51719b2010-07-29 18:18:33 -07003076 size_t numVirtualKeys = mLocked.virtualKeys.size();
3077 for (size_t i = 0; i < numVirtualKeys; i++) {
3078 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003079
3080 for (size_t i = 0; i < numCodes; i++) {
3081 if (virtualKey.keyCode == keyCodes[i]) {
3082 outFlags[i] = 1;
3083 }
3084 }
3085 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003086 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003087
3088 return true;
3089}
3090
3091
3092// --- SingleTouchInputMapper ---
3093
3094SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3095 TouchInputMapper(device, associatedDisplayId) {
3096 initialize();
3097}
3098
3099SingleTouchInputMapper::~SingleTouchInputMapper() {
3100}
3101
3102void SingleTouchInputMapper::initialize() {
3103 mAccumulator.clear();
3104
3105 mDown = false;
3106 mX = 0;
3107 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003108 mPressure = 0; // default to 0 for devices that don't report pressure
3109 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003110}
3111
3112void SingleTouchInputMapper::reset() {
3113 TouchInputMapper::reset();
3114
Jeff Browne57e8952010-07-23 21:28:06 -07003115 initialize();
3116 }
3117
3118void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3119 switch (rawEvent->type) {
3120 case EV_KEY:
3121 switch (rawEvent->scanCode) {
3122 case BTN_TOUCH:
3123 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3124 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003125 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3126 // not have received valid position information yet. This logic assumes that
3127 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003128 break;
3129 }
3130 break;
3131
3132 case EV_ABS:
3133 switch (rawEvent->scanCode) {
3134 case ABS_X:
3135 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3136 mAccumulator.absX = rawEvent->value;
3137 break;
3138 case ABS_Y:
3139 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3140 mAccumulator.absY = rawEvent->value;
3141 break;
3142 case ABS_PRESSURE:
3143 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3144 mAccumulator.absPressure = rawEvent->value;
3145 break;
3146 case ABS_TOOL_WIDTH:
3147 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3148 mAccumulator.absToolWidth = rawEvent->value;
3149 break;
3150 }
3151 break;
3152
3153 case EV_SYN:
3154 switch (rawEvent->scanCode) {
3155 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003156 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003157 break;
3158 }
3159 break;
3160 }
3161}
3162
3163void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003164 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003165 if (fields == 0) {
3166 return; // no new state changes, so nothing to do
3167 }
Jeff Browne57e8952010-07-23 21:28:06 -07003168
3169 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3170 mDown = mAccumulator.btnTouch;
3171 }
3172
3173 if (fields & Accumulator::FIELD_ABS_X) {
3174 mX = mAccumulator.absX;
3175 }
3176
3177 if (fields & Accumulator::FIELD_ABS_Y) {
3178 mY = mAccumulator.absY;
3179 }
3180
3181 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3182 mPressure = mAccumulator.absPressure;
3183 }
3184
3185 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003186 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003187 }
3188
3189 mCurrentTouch.clear();
3190
3191 if (mDown) {
3192 mCurrentTouch.pointerCount = 1;
3193 mCurrentTouch.pointers[0].id = 0;
3194 mCurrentTouch.pointers[0].x = mX;
3195 mCurrentTouch.pointers[0].y = mY;
3196 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003197 mCurrentTouch.pointers[0].touchMajor = 0;
3198 mCurrentTouch.pointers[0].touchMinor = 0;
3199 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3200 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003201 mCurrentTouch.pointers[0].orientation = 0;
3202 mCurrentTouch.idToIndex[0] = 0;
3203 mCurrentTouch.idBits.markBit(0);
3204 }
3205
3206 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003207
3208 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003209}
3210
Jeff Brown38a7fab2010-08-30 03:02:23 -07003211void SingleTouchInputMapper::configureRawAxes() {
3212 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003213
Jeff Brown38a7fab2010-08-30 03:02:23 -07003214 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3215 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3216 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3217 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003218}
3219
3220
3221// --- MultiTouchInputMapper ---
3222
3223MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3224 TouchInputMapper(device, associatedDisplayId) {
3225 initialize();
3226}
3227
3228MultiTouchInputMapper::~MultiTouchInputMapper() {
3229}
3230
3231void MultiTouchInputMapper::initialize() {
3232 mAccumulator.clear();
3233}
3234
3235void MultiTouchInputMapper::reset() {
3236 TouchInputMapper::reset();
3237
Jeff Browne57e8952010-07-23 21:28:06 -07003238 initialize();
3239}
3240
3241void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3242 switch (rawEvent->type) {
3243 case EV_ABS: {
3244 uint32_t pointerIndex = mAccumulator.pointerCount;
3245 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3246
3247 switch (rawEvent->scanCode) {
3248 case ABS_MT_POSITION_X:
3249 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3250 pointer->absMTPositionX = rawEvent->value;
3251 break;
3252 case ABS_MT_POSITION_Y:
3253 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3254 pointer->absMTPositionY = rawEvent->value;
3255 break;
3256 case ABS_MT_TOUCH_MAJOR:
3257 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3258 pointer->absMTTouchMajor = rawEvent->value;
3259 break;
3260 case ABS_MT_TOUCH_MINOR:
3261 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3262 pointer->absMTTouchMinor = rawEvent->value;
3263 break;
3264 case ABS_MT_WIDTH_MAJOR:
3265 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3266 pointer->absMTWidthMajor = rawEvent->value;
3267 break;
3268 case ABS_MT_WIDTH_MINOR:
3269 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3270 pointer->absMTWidthMinor = rawEvent->value;
3271 break;
3272 case ABS_MT_ORIENTATION:
3273 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3274 pointer->absMTOrientation = rawEvent->value;
3275 break;
3276 case ABS_MT_TRACKING_ID:
3277 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3278 pointer->absMTTrackingId = rawEvent->value;
3279 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003280 case ABS_MT_PRESSURE:
3281 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3282 pointer->absMTPressure = rawEvent->value;
3283 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003284 }
3285 break;
3286 }
3287
3288 case EV_SYN:
3289 switch (rawEvent->scanCode) {
3290 case SYN_MT_REPORT: {
3291 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3292 uint32_t pointerIndex = mAccumulator.pointerCount;
3293
3294 if (mAccumulator.pointers[pointerIndex].fields) {
3295 if (pointerIndex == MAX_POINTERS) {
3296 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3297 MAX_POINTERS);
3298 } else {
3299 pointerIndex += 1;
3300 mAccumulator.pointerCount = pointerIndex;
3301 }
3302 }
3303
3304 mAccumulator.pointers[pointerIndex].clear();
3305 break;
3306 }
3307
3308 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003309 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003310 break;
3311 }
3312 break;
3313 }
3314}
3315
3316void MultiTouchInputMapper::sync(nsecs_t when) {
3317 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003318 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003319
Jeff Browne57e8952010-07-23 21:28:06 -07003320 uint32_t inCount = mAccumulator.pointerCount;
3321 uint32_t outCount = 0;
3322 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003323
Jeff Browne57e8952010-07-23 21:28:06 -07003324 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003325
Jeff Browne57e8952010-07-23 21:28:06 -07003326 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003327 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3328 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003329
Jeff Browne57e8952010-07-23 21:28:06 -07003330 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003331 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3332 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003333 continue;
3334 }
3335
Jeff Brownd64c8552010-08-17 20:38:35 -07003336 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3337 outPointer.x = inPointer.absMTPositionX;
3338 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003339
Jeff Brown38a7fab2010-08-30 03:02:23 -07003340 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3341 if (inPointer.absMTPressure <= 0) {
3342 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brownd64c8552010-08-17 20:38:35 -07003343 // a pointer up. Drop this finger.
3344 continue;
3345 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003346 outPointer.pressure = inPointer.absMTPressure;
3347 } else {
3348 // Default pressure to 0 if absent.
3349 outPointer.pressure = 0;
3350 }
3351
3352 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3353 if (inPointer.absMTTouchMajor <= 0) {
3354 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3355 // a pointer going up. Drop this finger.
3356 continue;
3357 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003358 outPointer.touchMajor = inPointer.absMTTouchMajor;
3359 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003360 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003361 outPointer.touchMajor = 0;
3362 }
Jeff Browne839a582010-04-22 18:58:52 -07003363
Jeff Brownd64c8552010-08-17 20:38:35 -07003364 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3365 outPointer.touchMinor = inPointer.absMTTouchMinor;
3366 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003367 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003368 outPointer.touchMinor = outPointer.touchMajor;
3369 }
Jeff Browne839a582010-04-22 18:58:52 -07003370
Jeff Brownd64c8552010-08-17 20:38:35 -07003371 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3372 outPointer.toolMajor = inPointer.absMTWidthMajor;
3373 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003374 // Default tool area to 0 if absent.
3375 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003376 }
Jeff Browne839a582010-04-22 18:58:52 -07003377
Jeff Brownd64c8552010-08-17 20:38:35 -07003378 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3379 outPointer.toolMinor = inPointer.absMTWidthMinor;
3380 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003381 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003382 outPointer.toolMinor = outPointer.toolMajor;
3383 }
3384
3385 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3386 outPointer.orientation = inPointer.absMTOrientation;
3387 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003388 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003389 outPointer.orientation = 0;
3390 }
3391
Jeff Brown38a7fab2010-08-30 03:02:23 -07003392 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003393 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003394 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3395 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003396
Jeff Browne57e8952010-07-23 21:28:06 -07003397 if (id > MAX_POINTER_ID) {
3398#if DEBUG_POINTERS
3399 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003400 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003401 id, MAX_POINTER_ID);
3402#endif
3403 havePointerIds = false;
3404 }
3405 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003406 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003407 mCurrentTouch.idToIndex[id] = outCount;
3408 mCurrentTouch.idBits.markBit(id);
3409 }
3410 } else {
3411 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003412 }
3413 }
Jeff Browne839a582010-04-22 18:58:52 -07003414
Jeff Browne57e8952010-07-23 21:28:06 -07003415 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003416 }
3417
Jeff Browne57e8952010-07-23 21:28:06 -07003418 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003419
Jeff Browne57e8952010-07-23 21:28:06 -07003420 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003421
3422 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003423}
3424
Jeff Brown38a7fab2010-08-30 03:02:23 -07003425void MultiTouchInputMapper::configureRawAxes() {
3426 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003427
Jeff Brown38a7fab2010-08-30 03:02:23 -07003428 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3429 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3430 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3431 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3432 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3433 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3434 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3435 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003436}
3437
Jeff Browne839a582010-04-22 18:58:52 -07003438
3439} // namespace android