blob: 7adc764ab65dcf271ee72e7bc506b609324d2f29 [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
799bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
Jeff Browne57e8952010-07-23 21:28:06 -0700800 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
801}
802
803
804// --- SwitchInputMapper ---
805
806SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
807 InputMapper(device) {
808}
809
810SwitchInputMapper::~SwitchInputMapper() {
811}
812
813uint32_t SwitchInputMapper::getSources() {
814 return 0;
815}
816
817void SwitchInputMapper::process(const RawEvent* rawEvent) {
818 switch (rawEvent->type) {
819 case EV_SW:
820 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
821 break;
822 }
823}
824
825void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
826 uint32_t policyFlags = 0;
827 int32_t policyActions = getPolicy()->interceptSwitch(
828 when, switchCode, switchValue, policyFlags);
829
830 applyStandardPolicyActions(when, policyActions);
831}
832
833int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
834 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
835}
836
837
838// --- KeyboardInputMapper ---
839
840KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
841 uint32_t sources, int32_t keyboardType) :
842 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
843 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700844 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700845}
846
847KeyboardInputMapper::~KeyboardInputMapper() {
848}
849
Jeff Brownb51719b2010-07-29 18:18:33 -0700850void KeyboardInputMapper::initializeLocked() {
851 mLocked.metaState = AMETA_NONE;
852 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700853}
854
855uint32_t KeyboardInputMapper::getSources() {
856 return mSources;
857}
858
859void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
860 InputMapper::populateDeviceInfo(info);
861
862 info->setKeyboardType(mKeyboardType);
863}
864
Jeff Brown26c94ff2010-09-30 14:33:04 -0700865void KeyboardInputMapper::dump(String8& dump) {
866 { // acquire lock
867 AutoMutex _l(mLock);
868 dump.append(INDENT2 "Keyboard Input Mapper:\n");
869 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
Jeff Brown26c94ff2010-09-30 14:33:04 -0700870 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
871 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
872 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
873 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
874 } // release lock
875}
876
Jeff Browne57e8952010-07-23 21:28:06 -0700877void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700878 for (;;) {
879 int32_t keyCode, scanCode;
880 { // acquire lock
881 AutoMutex _l(mLock);
882
883 // Synthesize key up event on reset if keys are currently down.
884 if (mLocked.keyDowns.isEmpty()) {
885 initializeLocked();
886 break; // done
887 }
888
889 const KeyDown& keyDown = mLocked.keyDowns.top();
890 keyCode = keyDown.keyCode;
891 scanCode = keyDown.scanCode;
892 } // release lock
893
Jeff Browne57e8952010-07-23 21:28:06 -0700894 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700895 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700896 }
897
898 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700899 getContext()->updateGlobalMetaState();
900}
901
902void KeyboardInputMapper::process(const RawEvent* rawEvent) {
903 switch (rawEvent->type) {
904 case EV_KEY: {
905 int32_t scanCode = rawEvent->scanCode;
906 if (isKeyboardOrGamepadKey(scanCode)) {
907 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
908 rawEvent->flags);
909 }
910 break;
911 }
912 }
913}
914
915bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
916 return scanCode < BTN_MOUSE
917 || scanCode >= KEY_OK
918 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
919}
920
Jeff Brownb51719b2010-07-29 18:18:33 -0700921void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
922 int32_t scanCode, uint32_t policyFlags) {
923 int32_t newMetaState;
924 nsecs_t downTime;
925 bool metaStateChanged = false;
926
927 { // acquire lock
928 AutoMutex _l(mLock);
929
930 if (down) {
931 // Rotate key codes according to orientation if needed.
932 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
933 if (mAssociatedDisplayId >= 0) {
934 int32_t orientation;
935 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
936 return;
937 }
938
939 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700940 }
941
Jeff Brownb51719b2010-07-29 18:18:33 -0700942 // Add key down.
943 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
944 if (keyDownIndex >= 0) {
945 // key repeat, be sure to use same keycode as before in case of rotation
946 keyCode = mLocked.keyDowns.top().keyCode;
947 } else {
948 // key down
949 mLocked.keyDowns.push();
950 KeyDown& keyDown = mLocked.keyDowns.editTop();
951 keyDown.keyCode = keyCode;
952 keyDown.scanCode = scanCode;
953 }
954
955 mLocked.downTime = when;
956 } else {
957 // Remove key down.
958 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
959 if (keyDownIndex >= 0) {
960 // key up, be sure to use same keycode as before in case of rotation
961 keyCode = mLocked.keyDowns.top().keyCode;
962 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
963 } else {
964 // key was not actually down
965 LOGI("Dropping key up from device %s because the key was not down. "
966 "keyCode=%d, scanCode=%d",
967 getDeviceName().string(), keyCode, scanCode);
968 return;
969 }
Jeff Browne57e8952010-07-23 21:28:06 -0700970 }
971
Jeff Brownb51719b2010-07-29 18:18:33 -0700972 int32_t oldMetaState = mLocked.metaState;
973 newMetaState = updateMetaState(keyCode, down, oldMetaState);
974 if (oldMetaState != newMetaState) {
975 mLocked.metaState = newMetaState;
976 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700977 }
Jeff Brown8575a872010-06-30 16:10:35 -0700978
Jeff Brownb51719b2010-07-29 18:18:33 -0700979 downTime = mLocked.downTime;
980 } // release lock
981
982 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700983 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700984 }
985
Jeff Brownb51719b2010-07-29 18:18:33 -0700986 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
987}
Jeff Browne839a582010-04-22 18:58:52 -0700988
Jeff Brownb51719b2010-07-29 18:18:33 -0700989void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
990 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -0700991 int32_t policyActions = getPolicy()->interceptKey(when,
992 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700993
Jeff Browne57e8952010-07-23 21:28:06 -0700994 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Browne839a582010-04-22 18:58:52 -0700995 return; // event dropped
996 }
997
Jeff Brownb51719b2010-07-29 18:18:33 -0700998 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700999 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Browne57e8952010-07-23 21:28:06 -07001000 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brown956c0fb2010-10-01 14:55:30 -07001001 keyEventFlags |= AKEY_EVENT_FLAG_WOKE_HERE;
1002 }
1003 if (policyFlags & POLICY_FLAG_VIRTUAL) {
1004 keyEventFlags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
Jeff Browne839a582010-04-22 18:58:52 -07001005 }
1006
Jeff Browne57e8952010-07-23 21:28:06 -07001007 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brownb51719b2010-07-29 18:18:33 -07001008 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001009}
1010
Jeff Brownb51719b2010-07-29 18:18:33 -07001011ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1012 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -07001013 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001014 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07001015 return i;
1016 }
1017 }
1018 return -1;
Jeff Browne839a582010-04-22 18:58:52 -07001019}
1020
Jeff Browne57e8952010-07-23 21:28:06 -07001021int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1022 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1023}
Jeff Browne839a582010-04-22 18:58:52 -07001024
Jeff Browne57e8952010-07-23 21:28:06 -07001025int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1026 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1027}
Jeff Browne839a582010-04-22 18:58:52 -07001028
Jeff Browne57e8952010-07-23 21:28:06 -07001029bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1030 const int32_t* keyCodes, uint8_t* outFlags) {
1031 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1032}
1033
1034int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001035 { // acquire lock
1036 AutoMutex _l(mLock);
1037 return mLocked.metaState;
1038 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001039}
1040
1041
1042// --- TrackballInputMapper ---
1043
1044TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1045 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1046 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1047 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1048 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1049 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1050
Jeff Brownb51719b2010-07-29 18:18:33 -07001051 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001052}
1053
1054TrackballInputMapper::~TrackballInputMapper() {
1055}
1056
1057uint32_t TrackballInputMapper::getSources() {
1058 return AINPUT_SOURCE_TRACKBALL;
1059}
1060
1061void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1062 InputMapper::populateDeviceInfo(info);
1063
1064 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1065 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1066}
1067
Jeff Brown26c94ff2010-09-30 14:33:04 -07001068void TrackballInputMapper::dump(String8& dump) {
1069 { // acquire lock
1070 AutoMutex _l(mLock);
1071 dump.append(INDENT2 "Trackball Input Mapper:\n");
1072 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1073 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1074 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1075 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1076 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1077 } // release lock
1078}
1079
Jeff Brownb51719b2010-07-29 18:18:33 -07001080void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001081 mAccumulator.clear();
1082
Jeff Brownb51719b2010-07-29 18:18:33 -07001083 mLocked.down = false;
1084 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001085}
1086
1087void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001088 for (;;) {
1089 { // acquire lock
1090 AutoMutex _l(mLock);
1091
1092 if (! mLocked.down) {
1093 initializeLocked();
1094 break; // done
1095 }
1096 } // release lock
1097
1098 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001099 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001100 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001101 mAccumulator.btnMouse = false;
1102 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001103 }
1104
Jeff Browne57e8952010-07-23 21:28:06 -07001105 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001106}
Jeff Browne839a582010-04-22 18:58:52 -07001107
Jeff Browne57e8952010-07-23 21:28:06 -07001108void TrackballInputMapper::process(const RawEvent* rawEvent) {
1109 switch (rawEvent->type) {
1110 case EV_KEY:
1111 switch (rawEvent->scanCode) {
1112 case BTN_MOUSE:
1113 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1114 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001115 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1116 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001117 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001118 break;
Jeff Browne839a582010-04-22 18:58:52 -07001119 }
Jeff Browne57e8952010-07-23 21:28:06 -07001120 break;
Jeff Browne839a582010-04-22 18:58:52 -07001121
Jeff Browne57e8952010-07-23 21:28:06 -07001122 case EV_REL:
1123 switch (rawEvent->scanCode) {
1124 case REL_X:
1125 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1126 mAccumulator.relX = rawEvent->value;
1127 break;
1128 case REL_Y:
1129 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1130 mAccumulator.relY = rawEvent->value;
1131 break;
Jeff Browne839a582010-04-22 18:58:52 -07001132 }
Jeff Browne57e8952010-07-23 21:28:06 -07001133 break;
Jeff Browne839a582010-04-22 18:58:52 -07001134
Jeff Browne57e8952010-07-23 21:28:06 -07001135 case EV_SYN:
1136 switch (rawEvent->scanCode) {
1137 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001138 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001139 break;
Jeff Browne839a582010-04-22 18:58:52 -07001140 }
Jeff Browne57e8952010-07-23 21:28:06 -07001141 break;
Jeff Browne839a582010-04-22 18:58:52 -07001142 }
Jeff Browne839a582010-04-22 18:58:52 -07001143}
1144
Jeff Browne57e8952010-07-23 21:28:06 -07001145void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001146 uint32_t fields = mAccumulator.fields;
1147 if (fields == 0) {
1148 return; // no new state changes, so nothing to do
1149 }
1150
Jeff Brownb51719b2010-07-29 18:18:33 -07001151 int motionEventAction;
1152 PointerCoords pointerCoords;
1153 nsecs_t downTime;
1154 { // acquire lock
1155 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001156
Jeff Brownb51719b2010-07-29 18:18:33 -07001157 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1158
1159 if (downChanged) {
1160 if (mAccumulator.btnMouse) {
1161 mLocked.down = true;
1162 mLocked.downTime = when;
1163 } else {
1164 mLocked.down = false;
1165 }
Jeff Browne57e8952010-07-23 21:28:06 -07001166 }
Jeff Browne839a582010-04-22 18:58:52 -07001167
Jeff Brownb51719b2010-07-29 18:18:33 -07001168 downTime = mLocked.downTime;
1169 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1170 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001171
Jeff Brownb51719b2010-07-29 18:18:33 -07001172 if (downChanged) {
1173 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001174 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001175 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001176 }
Jeff Browne839a582010-04-22 18:58:52 -07001177
Jeff Brownb51719b2010-07-29 18:18:33 -07001178 pointerCoords.x = x;
1179 pointerCoords.y = y;
1180 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1181 pointerCoords.size = 0;
1182 pointerCoords.touchMajor = 0;
1183 pointerCoords.touchMinor = 0;
1184 pointerCoords.toolMajor = 0;
1185 pointerCoords.toolMinor = 0;
1186 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001187
Jeff Brownb51719b2010-07-29 18:18:33 -07001188 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1189 // Rotate motion based on display orientation if needed.
1190 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1191 int32_t orientation;
1192 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1193 return;
1194 }
1195
1196 float temp;
1197 switch (orientation) {
1198 case InputReaderPolicyInterface::ROTATION_90:
1199 temp = pointerCoords.x;
1200 pointerCoords.x = pointerCoords.y;
1201 pointerCoords.y = - temp;
1202 break;
1203
1204 case InputReaderPolicyInterface::ROTATION_180:
1205 pointerCoords.x = - pointerCoords.x;
1206 pointerCoords.y = - pointerCoords.y;
1207 break;
1208
1209 case InputReaderPolicyInterface::ROTATION_270:
1210 temp = pointerCoords.x;
1211 pointerCoords.x = - pointerCoords.y;
1212 pointerCoords.y = temp;
1213 break;
1214 }
1215 }
1216 } // release lock
1217
1218 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
Jeff Brownd64c8552010-08-17 20:38:35 -07001219
1220 mAccumulator.clear();
Jeff Brownb51719b2010-07-29 18:18:33 -07001221}
1222
1223void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1224 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001225 uint32_t policyFlags = 0;
1226 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1227
1228 if (! applyStandardPolicyActions(when, policyActions)) {
1229 return; // event dropped
1230 }
1231
Jeff Browne57e8952010-07-23 21:28:06 -07001232 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001233 int32_t pointerId = 0;
1234
Jeff Browne57e8952010-07-23 21:28:06 -07001235 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001236 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001237 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001238}
1239
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001240int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1241 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1242 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1243 } else {
1244 return AKEY_STATE_UNKNOWN;
1245 }
1246}
1247
Jeff Browne57e8952010-07-23 21:28:06 -07001248
1249// --- TouchInputMapper ---
1250
1251TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001252 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1253 mLocked.surfaceOrientation = -1;
1254 mLocked.surfaceWidth = -1;
1255 mLocked.surfaceHeight = -1;
1256
1257 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001258}
1259
1260TouchInputMapper::~TouchInputMapper() {
1261}
1262
1263uint32_t TouchInputMapper::getSources() {
1264 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1265}
1266
1267void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1268 InputMapper::populateDeviceInfo(info);
1269
Jeff Brownb51719b2010-07-29 18:18:33 -07001270 { // acquire lock
1271 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001272
Jeff Brownb51719b2010-07-29 18:18:33 -07001273 // Ensure surface information is up to date so that orientation changes are
1274 // noticed immediately.
1275 configureSurfaceLocked();
1276
1277 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1278 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001279
1280 if (mLocked.orientedRanges.havePressure) {
1281 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1282 mLocked.orientedRanges.pressure);
1283 }
1284
1285 if (mLocked.orientedRanges.haveSize) {
1286 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1287 mLocked.orientedRanges.size);
1288 }
1289
1290 if (mLocked.orientedRanges.haveTouchArea) {
1291 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1292 mLocked.orientedRanges.touchMajor);
1293 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1294 mLocked.orientedRanges.touchMinor);
1295 }
1296
1297 if (mLocked.orientedRanges.haveToolArea) {
1298 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1299 mLocked.orientedRanges.toolMajor);
1300 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1301 mLocked.orientedRanges.toolMinor);
1302 }
1303
1304 if (mLocked.orientedRanges.haveOrientation) {
1305 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1306 mLocked.orientedRanges.orientation);
1307 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001308 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001309}
1310
Jeff Brown26c94ff2010-09-30 14:33:04 -07001311void TouchInputMapper::dump(String8& dump) {
1312 { // acquire lock
1313 AutoMutex _l(mLock);
1314 dump.append(INDENT2 "Touch Input Mapper:\n");
1315 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1316 dumpParameters(dump);
1317 dumpVirtualKeysLocked(dump);
1318 dumpRawAxes(dump);
1319 dumpCalibration(dump);
1320 dumpSurfaceLocked(dump);
1321 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mLocked.xPrecision);
1322 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mLocked.yPrecision);
1323 } // release lock
1324}
1325
Jeff Brownb51719b2010-07-29 18:18:33 -07001326void TouchInputMapper::initializeLocked() {
1327 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001328 mLastTouch.clear();
1329 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001330
1331 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1332 mAveragingTouchFilter.historyStart[i] = 0;
1333 mAveragingTouchFilter.historyEnd[i] = 0;
1334 }
1335
1336 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001337
1338 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001339
1340 mLocked.orientedRanges.havePressure = false;
1341 mLocked.orientedRanges.haveSize = false;
1342 mLocked.orientedRanges.haveTouchArea = false;
1343 mLocked.orientedRanges.haveToolArea = false;
1344 mLocked.orientedRanges.haveOrientation = false;
1345}
1346
Jeff Browne57e8952010-07-23 21:28:06 -07001347void TouchInputMapper::configure() {
1348 InputMapper::configure();
1349
1350 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001351 configureParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001352
1353 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001354 configureRawAxes();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001355
1356 // Prepare input device calibration.
1357 parseCalibration();
1358 resolveCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001359
Jeff Brownb51719b2010-07-29 18:18:33 -07001360 { // acquire lock
1361 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001362
Jeff Brown38a7fab2010-08-30 03:02:23 -07001363 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001364 configureSurfaceLocked();
1365 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001366}
1367
Jeff Brown38a7fab2010-08-30 03:02:23 -07001368void TouchInputMapper::configureParameters() {
1369 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1370 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1371 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1372}
1373
Jeff Brown26c94ff2010-09-30 14:33:04 -07001374void TouchInputMapper::dumpParameters(String8& dump) {
1375 dump.appendFormat(INDENT3 "UseBadTouchFilter: %s\n",
1376 toString(mParameters.useBadTouchFilter));
1377 dump.appendFormat(INDENT3 "UseAveragingTouchFilter: %s\n",
1378 toString(mParameters.useAveragingTouchFilter));
1379 dump.appendFormat(INDENT3 "UseJumpyTouchFilter: %s\n",
1380 toString(mParameters.useJumpyTouchFilter));
Jeff Browna665ca82010-09-08 11:49:43 -07001381}
1382
Jeff Brown38a7fab2010-08-30 03:02:23 -07001383void TouchInputMapper::configureRawAxes() {
1384 mRawAxes.x.clear();
1385 mRawAxes.y.clear();
1386 mRawAxes.pressure.clear();
1387 mRawAxes.touchMajor.clear();
1388 mRawAxes.touchMinor.clear();
1389 mRawAxes.toolMajor.clear();
1390 mRawAxes.toolMinor.clear();
1391 mRawAxes.orientation.clear();
1392}
1393
Jeff Brown26c94ff2010-09-30 14:33:04 -07001394static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Browna665ca82010-09-08 11:49:43 -07001395 if (axis.valid) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001396 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Browna665ca82010-09-08 11:49:43 -07001397 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1398 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001399 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Browna665ca82010-09-08 11:49:43 -07001400 }
1401}
1402
Jeff Brown26c94ff2010-09-30 14:33:04 -07001403void TouchInputMapper::dumpRawAxes(String8& dump) {
1404 dump.append(INDENT3 "Raw Axes:\n");
1405 dumpAxisInfo(dump, mRawAxes.x, "X");
1406 dumpAxisInfo(dump, mRawAxes.y, "Y");
1407 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1408 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1409 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1410 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1411 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1412 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001413}
1414
Jeff Brownb51719b2010-07-29 18:18:33 -07001415bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001416 // Update orientation and dimensions if needed.
1417 int32_t orientation;
1418 int32_t width, height;
1419 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001420 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001421 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1422 return false;
1423 }
1424 } else {
1425 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001426 width = mRawAxes.x.getRange();
1427 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001428 }
1429
Jeff Brownb51719b2010-07-29 18:18:33 -07001430 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001431 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001432 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001433 }
1434
Jeff Brownb51719b2010-07-29 18:18:33 -07001435 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001436 if (sizeChanged) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001437 LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
1438 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001439
Jeff Brownb51719b2010-07-29 18:18:33 -07001440 mLocked.surfaceWidth = width;
1441 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001442
Jeff Brown38a7fab2010-08-30 03:02:23 -07001443 // Configure X and Y factors.
1444 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1445 mLocked.xOrigin = mRawAxes.x.minValue;
1446 mLocked.yOrigin = mRawAxes.y.minValue;
1447 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1448 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001449 mLocked.xPrecision = 1.0f / mLocked.xScale;
1450 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001451
Jeff Brownb51719b2010-07-29 18:18:33 -07001452 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001453 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001454 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001455 mLocked.xOrigin = 0;
1456 mLocked.yOrigin = 0;
1457 mLocked.xScale = 1.0f;
1458 mLocked.yScale = 1.0f;
1459 mLocked.xPrecision = 1.0f;
1460 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001461 }
1462
Jeff Brown38a7fab2010-08-30 03:02:23 -07001463 // Scale factor for terms that are not oriented in a particular axis.
1464 // If the pixels are square then xScale == yScale otherwise we fake it
1465 // by choosing an average.
1466 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001467
Jeff Brown38a7fab2010-08-30 03:02:23 -07001468 // Size of diagonal axis.
1469 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001470
Jeff Brown38a7fab2010-08-30 03:02:23 -07001471 // TouchMajor and TouchMinor factors.
1472 if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) {
1473 mLocked.orientedRanges.haveTouchArea = true;
1474 mLocked.orientedRanges.touchMajor.min = 0;
1475 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1476 mLocked.orientedRanges.touchMajor.flat = 0;
1477 mLocked.orientedRanges.touchMajor.fuzz = 0;
1478 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1479 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001480
Jeff Brown38a7fab2010-08-30 03:02:23 -07001481 // ToolMajor and ToolMinor factors.
1482 if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1483 mLocked.toolAreaLinearScale = 0;
1484 mLocked.toolAreaLinearBias = 0;
1485 if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) {
1486 if (mCalibration.haveToolAreaLinearScale) {
1487 mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale;
1488 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1489 mLocked.toolAreaLinearScale = float(min(width, height))
1490 / mRawAxes.toolMajor.maxValue;
1491 }
1492
1493 if (mCalibration.haveToolAreaLinearBias) {
1494 mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias;
1495 }
1496 }
1497
1498 mLocked.orientedRanges.haveToolArea = true;
1499 mLocked.orientedRanges.toolMajor.min = 0;
1500 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1501 mLocked.orientedRanges.toolMajor.flat = 0;
1502 mLocked.orientedRanges.toolMajor.fuzz = 0;
1503 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1504 }
1505
1506 // Pressure factors.
1507 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1508 RawAbsoluteAxisInfo rawPressureAxis;
1509 switch (mCalibration.pressureSource) {
1510 case Calibration::PRESSURE_SOURCE_PRESSURE:
1511 rawPressureAxis = mRawAxes.pressure;
1512 break;
1513 case Calibration::PRESSURE_SOURCE_TOUCH:
1514 rawPressureAxis = mRawAxes.touchMajor;
1515 break;
1516 default:
1517 rawPressureAxis.clear();
1518 }
1519
1520 mLocked.pressureScale = 0;
1521 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1522 || mCalibration.pressureCalibration
1523 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1524 if (mCalibration.havePressureScale) {
1525 mLocked.pressureScale = mCalibration.pressureScale;
1526 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1527 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1528 }
1529 }
1530
1531 mLocked.orientedRanges.havePressure = true;
1532 mLocked.orientedRanges.pressure.min = 0;
1533 mLocked.orientedRanges.pressure.max = 1.0;
1534 mLocked.orientedRanges.pressure.flat = 0;
1535 mLocked.orientedRanges.pressure.fuzz = 0;
1536 }
1537
1538 // Size factors.
1539 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1540 mLocked.sizeScale = 0;
1541 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1542 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1543 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1544 }
1545 }
1546
1547 mLocked.orientedRanges.haveSize = true;
1548 mLocked.orientedRanges.size.min = 0;
1549 mLocked.orientedRanges.size.max = 1.0;
1550 mLocked.orientedRanges.size.flat = 0;
1551 mLocked.orientedRanges.size.fuzz = 0;
1552 }
1553
1554 // Orientation
1555 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1556 mLocked.orientationScale = 0;
1557 if (mCalibration.orientationCalibration
1558 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1559 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1560 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1561 }
1562 }
1563
1564 mLocked.orientedRanges.orientation.min = - M_PI_2;
1565 mLocked.orientedRanges.orientation.max = M_PI_2;
1566 mLocked.orientedRanges.orientation.flat = 0;
1567 mLocked.orientedRanges.orientation.fuzz = 0;
1568 }
Jeff Browne57e8952010-07-23 21:28:06 -07001569 }
1570
1571 if (orientationChanged || sizeChanged) {
1572 // Compute oriented surface dimensions, precision, and scales.
1573 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001574 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001575 case InputReaderPolicyInterface::ROTATION_90:
1576 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001577 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1578 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1579 mLocked.orientedXPrecision = mLocked.yPrecision;
1580 mLocked.orientedYPrecision = mLocked.xPrecision;
1581 orientedXScale = mLocked.yScale;
1582 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001583 break;
1584 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001585 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1586 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1587 mLocked.orientedXPrecision = mLocked.xPrecision;
1588 mLocked.orientedYPrecision = mLocked.yPrecision;
1589 orientedXScale = mLocked.xScale;
1590 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001591 break;
1592 }
1593
1594 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001595 mLocked.orientedRanges.x.min = 0;
1596 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1597 mLocked.orientedRanges.x.flat = 0;
1598 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001599
Jeff Brownb51719b2010-07-29 18:18:33 -07001600 mLocked.orientedRanges.y.min = 0;
1601 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1602 mLocked.orientedRanges.y.flat = 0;
1603 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001604 }
1605
1606 return true;
1607}
1608
Jeff Brown26c94ff2010-09-30 14:33:04 -07001609void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1610 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1611 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1612 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Browna665ca82010-09-08 11:49:43 -07001613}
1614
Jeff Brownb51719b2010-07-29 18:18:33 -07001615void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001616 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001617
Jeff Brownb51719b2010-07-29 18:18:33 -07001618 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001619 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001620 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1621
Jeff Brownb51719b2010-07-29 18:18:33 -07001622 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001623
Jeff Brownb51719b2010-07-29 18:18:33 -07001624 if (virtualKeyDefinitions.size() == 0) {
1625 return;
1626 }
Jeff Browne57e8952010-07-23 21:28:06 -07001627
Jeff Brownb51719b2010-07-29 18:18:33 -07001628 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1629
Jeff Brown38a7fab2010-08-30 03:02:23 -07001630 int32_t touchScreenLeft = mRawAxes.x.minValue;
1631 int32_t touchScreenTop = mRawAxes.y.minValue;
1632 int32_t touchScreenWidth = mRawAxes.x.getRange();
1633 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001634
1635 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001636 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001637 virtualKeyDefinitions[i];
1638
1639 mLocked.virtualKeys.add();
1640 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1641
1642 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1643 int32_t keyCode;
1644 uint32_t flags;
1645 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1646 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001647 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1648 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001649 mLocked.virtualKeys.pop(); // drop the key
1650 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001651 }
1652
Jeff Brownb51719b2010-07-29 18:18:33 -07001653 virtualKey.keyCode = keyCode;
1654 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001655
Jeff Brownb51719b2010-07-29 18:18:33 -07001656 // convert the key definition's display coordinates into touch coordinates for a hit box
1657 int32_t halfWidth = virtualKeyDefinition.width / 2;
1658 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001659
Jeff Brownb51719b2010-07-29 18:18:33 -07001660 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1661 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1662 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1663 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1664 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1665 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1666 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1667 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001668
Jeff Brown26c94ff2010-09-30 14:33:04 -07001669 }
1670}
1671
1672void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1673 if (!mLocked.virtualKeys.isEmpty()) {
1674 dump.append(INDENT3 "Virtual Keys:\n");
1675
1676 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1677 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1678 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1679 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1680 i, virtualKey.scanCode, virtualKey.keyCode,
1681 virtualKey.hitLeft, virtualKey.hitRight,
1682 virtualKey.hitTop, virtualKey.hitBottom);
1683 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001684 }
Jeff Browne57e8952010-07-23 21:28:06 -07001685}
1686
Jeff Brown38a7fab2010-08-30 03:02:23 -07001687void TouchInputMapper::parseCalibration() {
1688 const InputDeviceCalibration& in = getDevice()->getCalibration();
1689 Calibration& out = mCalibration;
1690
1691 // Touch Area
1692 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT;
1693 String8 touchAreaCalibrationString;
1694 if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) {
1695 if (touchAreaCalibrationString == "none") {
1696 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1697 } else if (touchAreaCalibrationString == "geometric") {
1698 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC;
1699 } else if (touchAreaCalibrationString == "pressure") {
1700 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1701 } else if (touchAreaCalibrationString != "default") {
1702 LOGW("Invalid value for touch.touchArea.calibration: '%s'",
1703 touchAreaCalibrationString.string());
1704 }
1705 }
1706
1707 // Tool Area
1708 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT;
1709 String8 toolAreaCalibrationString;
1710 if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) {
1711 if (toolAreaCalibrationString == "none") {
1712 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1713 } else if (toolAreaCalibrationString == "geometric") {
1714 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC;
1715 } else if (toolAreaCalibrationString == "linear") {
1716 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1717 } else if (toolAreaCalibrationString != "default") {
1718 LOGW("Invalid value for tool.toolArea.calibration: '%s'",
1719 toolAreaCalibrationString.string());
1720 }
1721 }
1722
1723 out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"),
1724 out.toolAreaLinearScale);
1725 out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"),
1726 out.toolAreaLinearBias);
1727 out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"),
1728 out.toolAreaIsSummed);
1729
1730 // Pressure
1731 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1732 String8 pressureCalibrationString;
1733 if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) {
1734 if (pressureCalibrationString == "none") {
1735 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1736 } else if (pressureCalibrationString == "physical") {
1737 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1738 } else if (pressureCalibrationString == "amplitude") {
1739 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1740 } else if (pressureCalibrationString != "default") {
1741 LOGW("Invalid value for tool.pressure.calibration: '%s'",
1742 pressureCalibrationString.string());
1743 }
1744 }
1745
1746 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1747 String8 pressureSourceString;
1748 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1749 if (pressureSourceString == "pressure") {
1750 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1751 } else if (pressureSourceString == "touch") {
1752 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1753 } else if (pressureSourceString != "default") {
1754 LOGW("Invalid value for touch.pressure.source: '%s'",
1755 pressureSourceString.string());
1756 }
1757 }
1758
1759 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1760 out.pressureScale);
1761
1762 // Size
1763 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1764 String8 sizeCalibrationString;
1765 if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) {
1766 if (sizeCalibrationString == "none") {
1767 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1768 } else if (sizeCalibrationString == "normalized") {
1769 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1770 } else if (sizeCalibrationString != "default") {
1771 LOGW("Invalid value for tool.size.calibration: '%s'",
1772 sizeCalibrationString.string());
1773 }
1774 }
1775
1776 // Orientation
1777 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1778 String8 orientationCalibrationString;
1779 if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) {
1780 if (orientationCalibrationString == "none") {
1781 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1782 } else if (orientationCalibrationString == "interpolated") {
1783 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1784 } else if (orientationCalibrationString != "default") {
1785 LOGW("Invalid value for tool.orientation.calibration: '%s'",
1786 orientationCalibrationString.string());
1787 }
1788 }
1789}
1790
1791void TouchInputMapper::resolveCalibration() {
1792 // Pressure
1793 switch (mCalibration.pressureSource) {
1794 case Calibration::PRESSURE_SOURCE_DEFAULT:
1795 if (mRawAxes.pressure.valid) {
1796 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1797 } else if (mRawAxes.touchMajor.valid) {
1798 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1799 }
1800 break;
1801
1802 case Calibration::PRESSURE_SOURCE_PRESSURE:
1803 if (! mRawAxes.pressure.valid) {
1804 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1805 "the pressure axis is not available.");
1806 }
1807 break;
1808
1809 case Calibration::PRESSURE_SOURCE_TOUCH:
1810 if (! mRawAxes.touchMajor.valid) {
1811 LOGW("Calibration property touch.pressure.source is 'touch' but "
1812 "the touchMajor axis is not available.");
1813 }
1814 break;
1815
1816 default:
1817 break;
1818 }
1819
1820 switch (mCalibration.pressureCalibration) {
1821 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1822 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1823 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1824 } else {
1825 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1826 }
1827 break;
1828
1829 default:
1830 break;
1831 }
1832
1833 // Tool Area
1834 switch (mCalibration.toolAreaCalibration) {
1835 case Calibration::TOOL_AREA_CALIBRATION_DEFAULT:
1836 if (mRawAxes.toolMajor.valid) {
1837 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1838 } else {
1839 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1840 }
1841 break;
1842
1843 default:
1844 break;
1845 }
1846
1847 // Touch Area
1848 switch (mCalibration.touchAreaCalibration) {
1849 case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT:
1850 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
1851 && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1852 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1853 } else {
1854 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1855 }
1856 break;
1857
1858 default:
1859 break;
1860 }
1861
1862 // Size
1863 switch (mCalibration.sizeCalibration) {
1864 case Calibration::SIZE_CALIBRATION_DEFAULT:
1865 if (mRawAxes.toolMajor.valid) {
1866 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1867 } else {
1868 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1869 }
1870 break;
1871
1872 default:
1873 break;
1874 }
1875
1876 // Orientation
1877 switch (mCalibration.orientationCalibration) {
1878 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1879 if (mRawAxes.orientation.valid) {
1880 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1881 } else {
1882 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1883 }
1884 break;
1885
1886 default:
1887 break;
1888 }
1889}
1890
Jeff Brown26c94ff2010-09-30 14:33:04 -07001891void TouchInputMapper::dumpCalibration(String8& dump) {
1892 dump.append(INDENT3 "Calibration:\n");
Jeff Browna665ca82010-09-08 11:49:43 -07001893
Jeff Brown38a7fab2010-08-30 03:02:23 -07001894 // Touch Area
1895 switch (mCalibration.touchAreaCalibration) {
1896 case Calibration::TOUCH_AREA_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001897 dump.append(INDENT4 "touch.touchArea.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001898 break;
1899 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001900 dump.append(INDENT4 "touch.touchArea.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001901 break;
1902 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001903 dump.append(INDENT4 "touch.touchArea.calibration: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001904 break;
1905 default:
1906 assert(false);
1907 }
1908
1909 // Tool Area
1910 switch (mCalibration.toolAreaCalibration) {
1911 case Calibration::TOOL_AREA_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001912 dump.append(INDENT4 "touch.toolArea.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001913 break;
1914 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001915 dump.append(INDENT4 "touch.toolArea.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001916 break;
1917 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001918 dump.append(INDENT4 "touch.toolArea.calibration: linear\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001919 break;
1920 default:
1921 assert(false);
1922 }
1923
1924 if (mCalibration.haveToolAreaLinearScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001925 dump.appendFormat(INDENT4 "touch.toolArea.linearScale: %0.3f\n",
1926 mCalibration.toolAreaLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001927 }
1928
1929 if (mCalibration.haveToolAreaLinearBias) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001930 dump.appendFormat(INDENT4 "touch.toolArea.linearBias: %0.3f\n",
1931 mCalibration.toolAreaLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001932 }
1933
1934 if (mCalibration.haveToolAreaIsSummed) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001935 dump.appendFormat(INDENT4 "touch.toolArea.isSummed: %d\n",
1936 mCalibration.toolAreaIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001937 }
1938
1939 // Pressure
1940 switch (mCalibration.pressureCalibration) {
1941 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001942 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001943 break;
1944 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001945 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001946 break;
1947 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001948 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001949 break;
1950 default:
1951 assert(false);
1952 }
1953
1954 switch (mCalibration.pressureSource) {
1955 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001956 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001957 break;
1958 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001959 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001960 break;
1961 case Calibration::PRESSURE_SOURCE_DEFAULT:
1962 break;
1963 default:
1964 assert(false);
1965 }
1966
1967 if (mCalibration.havePressureScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001968 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
1969 mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001970 }
1971
1972 // Size
1973 switch (mCalibration.sizeCalibration) {
1974 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001975 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001976 break;
1977 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001978 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001979 break;
1980 default:
1981 assert(false);
1982 }
1983
1984 // Orientation
1985 switch (mCalibration.orientationCalibration) {
1986 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001987 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001988 break;
1989 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001990 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001991 break;
1992 default:
1993 assert(false);
1994 }
1995}
1996
Jeff Browne57e8952010-07-23 21:28:06 -07001997void TouchInputMapper::reset() {
1998 // Synthesize touch up event if touch is currently down.
1999 // This will also take care of finishing virtual key processing if needed.
2000 if (mLastTouch.pointerCount != 0) {
2001 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2002 mCurrentTouch.clear();
2003 syncTouch(when, true);
2004 }
2005
Jeff Brownb51719b2010-07-29 18:18:33 -07002006 { // acquire lock
2007 AutoMutex _l(mLock);
2008 initializeLocked();
2009 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002010
Jeff Brownb51719b2010-07-29 18:18:33 -07002011 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07002012}
2013
2014void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002015 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07002016
2017 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07002018 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
2019
2020 if (! applyStandardPolicyActions(when, policyActions)) {
2021 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07002022 return; // event dropped
2023 }
2024
Jeff Brownb51719b2010-07-29 18:18:33 -07002025 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07002026
Jeff Browne57e8952010-07-23 21:28:06 -07002027 if (mParameters.useBadTouchFilter) {
2028 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002029 havePointerIds = false;
2030 }
2031 }
2032
Jeff Browne57e8952010-07-23 21:28:06 -07002033 if (mParameters.useJumpyTouchFilter) {
2034 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002035 havePointerIds = false;
2036 }
2037 }
2038
2039 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002040 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002041 }
2042
Jeff Browne57e8952010-07-23 21:28:06 -07002043 TouchData temp;
2044 TouchData* savedTouch;
2045 if (mParameters.useAveragingTouchFilter) {
2046 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002047 savedTouch = & temp;
2048
Jeff Browne57e8952010-07-23 21:28:06 -07002049 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002050 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002051 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002052 }
2053
Jeff Brownb51719b2010-07-29 18:18:33 -07002054 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002055
Jeff Browne57e8952010-07-23 21:28:06 -07002056 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2057 if (touchResult == DISPATCH_TOUCH) {
2058 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002059 }
2060
Jeff Brownb51719b2010-07-29 18:18:33 -07002061 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002062
Jeff Browne57e8952010-07-23 21:28:06 -07002063 if (touchResult == DROP_STROKE) {
2064 mLastTouch.clear();
2065 } else {
2066 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002067 }
Jeff Browne839a582010-04-22 18:58:52 -07002068}
2069
Jeff Browne57e8952010-07-23 21:28:06 -07002070TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2071 nsecs_t when, uint32_t policyFlags) {
2072 int32_t keyEventAction, keyEventFlags;
2073 int32_t keyCode, scanCode, downTime;
2074 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002075
Jeff Brownb51719b2010-07-29 18:18:33 -07002076 { // acquire lock
2077 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002078
Jeff Brownb51719b2010-07-29 18:18:33 -07002079 // Update surface size and orientation, including virtual key positions.
2080 if (! configureSurfaceLocked()) {
2081 return DROP_STROKE;
2082 }
2083
2084 // Check for virtual key press.
2085 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002086 if (mCurrentTouch.pointerCount == 0) {
2087 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002088 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002089#if DEBUG_VIRTUAL_KEYS
2090 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2091 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2092#endif
2093 keyEventAction = AKEY_EVENT_ACTION_UP;
2094 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2095 touchResult = SKIP_TOUCH;
2096 goto DispatchVirtualKey;
2097 }
2098
2099 if (mCurrentTouch.pointerCount == 1) {
2100 int32_t x = mCurrentTouch.pointers[0].x;
2101 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002102 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2103 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002104 // Pointer is still within the space of the virtual key.
2105 return SKIP_TOUCH;
2106 }
2107 }
2108
2109 // Pointer left virtual key area or another pointer also went down.
2110 // Send key cancellation and drop the stroke so subsequent motions will be
2111 // considered fresh downs. This is useful when the user swipes away from the
2112 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002113 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002114#if DEBUG_VIRTUAL_KEYS
2115 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2116 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2117#endif
2118 keyEventAction = AKEY_EVENT_ACTION_UP;
2119 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2120 | AKEY_EVENT_FLAG_CANCELED;
2121 touchResult = DROP_STROKE;
2122 goto DispatchVirtualKey;
2123 } else {
2124 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2125 // Pointer just went down. Handle off-screen touches, if needed.
2126 int32_t x = mCurrentTouch.pointers[0].x;
2127 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002128 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002129 // If exactly one pointer went down, check for virtual key hit.
2130 // Otherwise we will drop the entire stroke.
2131 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002132 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002133 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002134 mLocked.currentVirtualKey.down = true;
2135 mLocked.currentVirtualKey.downTime = when;
2136 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2137 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002138#if DEBUG_VIRTUAL_KEYS
2139 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2140 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2141#endif
2142 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2143 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2144 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2145 touchResult = SKIP_TOUCH;
2146 goto DispatchVirtualKey;
2147 }
2148 }
2149 return DROP_STROKE;
2150 }
2151 }
2152 return DISPATCH_TOUCH;
2153 }
2154
2155 DispatchVirtualKey:
2156 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002157 keyCode = mLocked.currentVirtualKey.keyCode;
2158 scanCode = mLocked.currentVirtualKey.scanCode;
2159 downTime = mLocked.currentVirtualKey.downTime;
2160 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002161
2162 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002163 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
2164 keyCode, scanCode, downTime);
2165 return touchResult;
2166}
2167
2168void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
2169 int32_t keyEventAction, int32_t keyEventFlags,
2170 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07002171 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07002172
Jeff Brown956c0fb2010-10-01 14:55:30 -07002173 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Browne57e8952010-07-23 21:28:06 -07002174 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002175 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07002176
Jeff Browne57e8952010-07-23 21:28:06 -07002177 if (applyStandardPolicyActions(when, policyActions)) {
2178 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07002179 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2180 }
Jeff Browne839a582010-04-22 18:58:52 -07002181}
2182
Jeff Browne57e8952010-07-23 21:28:06 -07002183void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2184 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2185 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002186 if (currentPointerCount == 0 && lastPointerCount == 0) {
2187 return; // nothing to do!
2188 }
2189
Jeff Browne57e8952010-07-23 21:28:06 -07002190 BitSet32 currentIdBits = mCurrentTouch.idBits;
2191 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002192
2193 if (currentIdBits == lastIdBits) {
2194 // No pointer id changes so this is a move event.
2195 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002196 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002197 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002198 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002199 } else {
2200 // There may be pointers going up and pointers going down at the same time when pointer
2201 // ids are reported by the device driver.
2202 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2203 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2204 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002205 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002206
2207 while (! upIdBits.isEmpty()) {
2208 uint32_t upId = upIdBits.firstMarkedBit();
2209 upIdBits.clearBit(upId);
2210 BitSet32 oldActiveIdBits = activeIdBits;
2211 activeIdBits.clearBit(upId);
2212
2213 int32_t motionEventAction;
2214 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002215 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002216 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002217 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002218 }
2219
Jeff Browne57e8952010-07-23 21:28:06 -07002220 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002221 oldActiveIdBits, upId, pointerCount, motionEventAction);
2222 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002223 }
2224
2225 while (! downIdBits.isEmpty()) {
2226 uint32_t downId = downIdBits.firstMarkedBit();
2227 downIdBits.clearBit(downId);
2228 BitSet32 oldActiveIdBits = activeIdBits;
2229 activeIdBits.markBit(downId);
2230
2231 int32_t motionEventAction;
2232 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002233 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002234 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002235 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002236 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002237 }
2238
Jeff Brown38a7fab2010-08-30 03:02:23 -07002239 pointerCount += 1;
Jeff Browne57e8952010-07-23 21:28:06 -07002240 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002241 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002242 }
2243 }
2244}
2245
Jeff Browne57e8952010-07-23 21:28:06 -07002246void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002247 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002248 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002249 int32_t pointerIds[MAX_POINTERS];
2250 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002251 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002252 float xPrecision, yPrecision;
2253
2254 { // acquire lock
2255 AutoMutex _l(mLock);
2256
2257 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2258 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002259 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002260 uint32_t id = idBits.firstMarkedBit();
2261 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002262 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002263
Jeff Brown38a7fab2010-08-30 03:02:23 -07002264 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002265
Jeff Brown38a7fab2010-08-30 03:02:23 -07002266 // X and Y
2267 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2268 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002269
Jeff Brown38a7fab2010-08-30 03:02:23 -07002270 // ToolMajor and ToolMinor
2271 float toolMajor, toolMinor;
2272 switch (mCalibration.toolAreaCalibration) {
2273 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
2274 toolMajor = in.toolMajor * mLocked.geometricScale;
2275 if (mRawAxes.toolMinor.valid) {
2276 toolMinor = in.toolMinor * mLocked.geometricScale;
2277 } else {
2278 toolMinor = toolMajor;
2279 }
2280 break;
2281 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
2282 toolMajor = in.toolMajor != 0
2283 ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias
2284 : 0;
2285 if (mRawAxes.toolMinor.valid) {
2286 toolMinor = in.toolMinor != 0
2287 ? in.toolMinor * mLocked.toolAreaLinearScale
2288 + mLocked.toolAreaLinearBias
2289 : 0;
2290 } else {
2291 toolMinor = toolMajor;
2292 }
2293 break;
2294 default:
2295 toolMajor = 0;
2296 toolMinor = 0;
2297 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002298 }
2299
Jeff Brown38a7fab2010-08-30 03:02:23 -07002300 if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) {
2301 toolMajor /= pointerCount;
2302 toolMinor /= pointerCount;
2303 }
2304
2305 // Pressure
2306 float rawPressure;
2307 switch (mCalibration.pressureSource) {
2308 case Calibration::PRESSURE_SOURCE_PRESSURE:
2309 rawPressure = in.pressure;
2310 break;
2311 case Calibration::PRESSURE_SOURCE_TOUCH:
2312 rawPressure = in.touchMajor;
2313 break;
2314 default:
2315 rawPressure = 0;
2316 }
2317
2318 float pressure;
2319 switch (mCalibration.pressureCalibration) {
2320 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2321 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2322 pressure = rawPressure * mLocked.pressureScale;
2323 break;
2324 default:
2325 pressure = 1;
2326 break;
2327 }
2328
2329 // TouchMajor and TouchMinor
2330 float touchMajor, touchMinor;
2331 switch (mCalibration.touchAreaCalibration) {
2332 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
2333 touchMajor = in.touchMajor * mLocked.geometricScale;
2334 if (mRawAxes.touchMinor.valid) {
2335 touchMinor = in.touchMinor * mLocked.geometricScale;
2336 } else {
2337 touchMinor = touchMajor;
2338 }
2339 break;
2340 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
2341 touchMajor = toolMajor * pressure;
2342 touchMinor = toolMinor * pressure;
2343 break;
2344 default:
2345 touchMajor = 0;
2346 touchMinor = 0;
2347 break;
2348 }
2349
2350 if (touchMajor > toolMajor) {
2351 touchMajor = toolMajor;
2352 }
2353 if (touchMinor > toolMinor) {
2354 touchMinor = toolMinor;
2355 }
2356
2357 // Size
2358 float size;
2359 switch (mCalibration.sizeCalibration) {
2360 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2361 float rawSize = mRawAxes.toolMinor.valid
2362 ? avg(in.toolMajor, in.toolMinor)
2363 : in.toolMajor;
2364 size = rawSize * mLocked.sizeScale;
2365 break;
2366 }
2367 default:
2368 size = 0;
2369 break;
2370 }
2371
2372 // Orientation
2373 float orientation;
2374 switch (mCalibration.orientationCalibration) {
2375 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2376 orientation = in.orientation * mLocked.orientationScale;
2377 break;
2378 default:
2379 orientation = 0;
2380 }
2381
2382 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002383 switch (mLocked.surfaceOrientation) {
2384 case InputReaderPolicyInterface::ROTATION_90: {
2385 float xTemp = x;
2386 x = y;
2387 y = mLocked.surfaceWidth - xTemp;
2388 orientation -= M_PI_2;
2389 if (orientation < - M_PI_2) {
2390 orientation += M_PI;
2391 }
2392 break;
2393 }
2394 case InputReaderPolicyInterface::ROTATION_180: {
2395 x = mLocked.surfaceWidth - x;
2396 y = mLocked.surfaceHeight - y;
2397 orientation = - orientation;
2398 break;
2399 }
2400 case InputReaderPolicyInterface::ROTATION_270: {
2401 float xTemp = x;
2402 x = mLocked.surfaceHeight - y;
2403 y = xTemp;
2404 orientation += M_PI_2;
2405 if (orientation > M_PI_2) {
2406 orientation -= M_PI;
2407 }
2408 break;
2409 }
2410 }
2411
Jeff Brown38a7fab2010-08-30 03:02:23 -07002412 // Write output coords.
2413 PointerCoords& out = pointerCoords[outIndex];
2414 out.x = x;
2415 out.y = y;
2416 out.pressure = pressure;
2417 out.size = size;
2418 out.touchMajor = touchMajor;
2419 out.touchMinor = touchMinor;
2420 out.toolMajor = toolMajor;
2421 out.toolMinor = toolMinor;
2422 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002423
Jeff Brown38a7fab2010-08-30 03:02:23 -07002424 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002425
2426 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002427 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002428 }
Jeff Browne839a582010-04-22 18:58:52 -07002429 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002430
2431 // Check edge flags by looking only at the first pointer since the flags are
2432 // global to the event.
2433 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2434 if (pointerCoords[0].x <= 0) {
2435 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2436 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2437 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2438 }
2439 if (pointerCoords[0].y <= 0) {
2440 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2441 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2442 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2443 }
Jeff Browne839a582010-04-22 18:58:52 -07002444 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002445
2446 xPrecision = mLocked.orientedXPrecision;
2447 yPrecision = mLocked.orientedYPrecision;
2448 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002449
Jeff Brown77e26fc2010-10-07 13:44:51 -07002450 getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002451 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002452 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002453 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002454}
2455
Jeff Brownb51719b2010-07-29 18:18:33 -07002456bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002457 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2458 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2459 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002460 }
Jeff Browne57e8952010-07-23 21:28:06 -07002461 return true;
2462}
2463
Jeff Brownb51719b2010-07-29 18:18:33 -07002464const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2465 int32_t x, int32_t y) {
2466 size_t numVirtualKeys = mLocked.virtualKeys.size();
2467 for (size_t i = 0; i < numVirtualKeys; i++) {
2468 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002469
2470#if DEBUG_VIRTUAL_KEYS
2471 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2472 "left=%d, top=%d, right=%d, bottom=%d",
2473 x, y,
2474 virtualKey.keyCode, virtualKey.scanCode,
2475 virtualKey.hitLeft, virtualKey.hitTop,
2476 virtualKey.hitRight, virtualKey.hitBottom);
2477#endif
2478
2479 if (virtualKey.isHit(x, y)) {
2480 return & virtualKey;
2481 }
2482 }
2483
2484 return NULL;
2485}
2486
2487void TouchInputMapper::calculatePointerIds() {
2488 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2489 uint32_t lastPointerCount = mLastTouch.pointerCount;
2490
2491 if (currentPointerCount == 0) {
2492 // No pointers to assign.
2493 mCurrentTouch.idBits.clear();
2494 } else if (lastPointerCount == 0) {
2495 // All pointers are new.
2496 mCurrentTouch.idBits.clear();
2497 for (uint32_t i = 0; i < currentPointerCount; i++) {
2498 mCurrentTouch.pointers[i].id = i;
2499 mCurrentTouch.idToIndex[i] = i;
2500 mCurrentTouch.idBits.markBit(i);
2501 }
2502 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2503 // Only one pointer and no change in count so it must have the same id as before.
2504 uint32_t id = mLastTouch.pointers[0].id;
2505 mCurrentTouch.pointers[0].id = id;
2506 mCurrentTouch.idToIndex[id] = 0;
2507 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2508 } else {
2509 // General case.
2510 // We build a heap of squared euclidean distances between current and last pointers
2511 // associated with the current and last pointer indices. Then, we find the best
2512 // match (by distance) for each current pointer.
2513 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2514
2515 uint32_t heapSize = 0;
2516 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2517 currentPointerIndex++) {
2518 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2519 lastPointerIndex++) {
2520 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2521 - mLastTouch.pointers[lastPointerIndex].x;
2522 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2523 - mLastTouch.pointers[lastPointerIndex].y;
2524
2525 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2526
2527 // Insert new element into the heap (sift up).
2528 heap[heapSize].currentPointerIndex = currentPointerIndex;
2529 heap[heapSize].lastPointerIndex = lastPointerIndex;
2530 heap[heapSize].distance = distance;
2531 heapSize += 1;
2532 }
2533 }
2534
2535 // Heapify
2536 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2537 startIndex -= 1;
2538 for (uint32_t parentIndex = startIndex; ;) {
2539 uint32_t childIndex = parentIndex * 2 + 1;
2540 if (childIndex >= heapSize) {
2541 break;
2542 }
2543
2544 if (childIndex + 1 < heapSize
2545 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2546 childIndex += 1;
2547 }
2548
2549 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2550 break;
2551 }
2552
2553 swap(heap[parentIndex], heap[childIndex]);
2554 parentIndex = childIndex;
2555 }
2556 }
2557
2558#if DEBUG_POINTER_ASSIGNMENT
2559 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2560 for (size_t i = 0; i < heapSize; i++) {
2561 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2562 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2563 heap[i].distance);
2564 }
2565#endif
2566
2567 // Pull matches out by increasing order of distance.
2568 // To avoid reassigning pointers that have already been matched, the loop keeps track
2569 // of which last and current pointers have been matched using the matchedXXXBits variables.
2570 // It also tracks the used pointer id bits.
2571 BitSet32 matchedLastBits(0);
2572 BitSet32 matchedCurrentBits(0);
2573 BitSet32 usedIdBits(0);
2574 bool first = true;
2575 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2576 for (;;) {
2577 if (first) {
2578 // The first time through the loop, we just consume the root element of
2579 // the heap (the one with smallest distance).
2580 first = false;
2581 } else {
2582 // Previous iterations consumed the root element of the heap.
2583 // Pop root element off of the heap (sift down).
2584 heapSize -= 1;
2585 assert(heapSize > 0);
2586
2587 // Sift down.
2588 heap[0] = heap[heapSize];
2589 for (uint32_t parentIndex = 0; ;) {
2590 uint32_t childIndex = parentIndex * 2 + 1;
2591 if (childIndex >= heapSize) {
2592 break;
2593 }
2594
2595 if (childIndex + 1 < heapSize
2596 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2597 childIndex += 1;
2598 }
2599
2600 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2601 break;
2602 }
2603
2604 swap(heap[parentIndex], heap[childIndex]);
2605 parentIndex = childIndex;
2606 }
2607
2608#if DEBUG_POINTER_ASSIGNMENT
2609 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2610 for (size_t i = 0; i < heapSize; i++) {
2611 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2612 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2613 heap[i].distance);
2614 }
2615#endif
2616 }
2617
2618 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2619 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2620
2621 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2622 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2623
2624 matchedCurrentBits.markBit(currentPointerIndex);
2625 matchedLastBits.markBit(lastPointerIndex);
2626
2627 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2628 mCurrentTouch.pointers[currentPointerIndex].id = id;
2629 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2630 usedIdBits.markBit(id);
2631
2632#if DEBUG_POINTER_ASSIGNMENT
2633 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2634 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2635#endif
2636 break;
2637 }
2638 }
2639
2640 // Assign fresh ids to new pointers.
2641 if (currentPointerCount > lastPointerCount) {
2642 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2643 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2644 uint32_t id = usedIdBits.firstUnmarkedBit();
2645
2646 mCurrentTouch.pointers[currentPointerIndex].id = id;
2647 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2648 usedIdBits.markBit(id);
2649
2650#if DEBUG_POINTER_ASSIGNMENT
2651 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2652 currentPointerIndex, id);
2653#endif
2654
2655 if (--i == 0) break; // done
2656 matchedCurrentBits.markBit(currentPointerIndex);
2657 }
2658 }
2659
2660 // Fix id bits.
2661 mCurrentTouch.idBits = usedIdBits;
2662 }
2663}
2664
2665/* Special hack for devices that have bad screen data: if one of the
2666 * points has moved more than a screen height from the last position,
2667 * then drop it. */
2668bool TouchInputMapper::applyBadTouchFilter() {
2669 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002670 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002671 return false;
2672 }
2673
2674 uint32_t pointerCount = mCurrentTouch.pointerCount;
2675
2676 // Nothing to do if there are no points.
2677 if (pointerCount == 0) {
2678 return false;
2679 }
2680
2681 // Don't do anything if a finger is going down or up. We run
2682 // here before assigning pointer IDs, so there isn't a good
2683 // way to do per-finger matching.
2684 if (pointerCount != mLastTouch.pointerCount) {
2685 return false;
2686 }
2687
2688 // We consider a single movement across more than a 7/16 of
2689 // the long size of the screen to be bad. This was a magic value
2690 // determined by looking at the maximum distance it is feasible
2691 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002692 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002693
2694 // XXX The original code in InputDevice.java included commented out
2695 // code for testing the X axis. Note that when we drop a point
2696 // we don't actually restore the old X either. Strange.
2697 // The old code also tries to track when bad points were previously
2698 // detected but it turns out that due to the placement of a "break"
2699 // at the end of the loop, we never set mDroppedBadPoint to true
2700 // so it is effectively dead code.
2701 // Need to figure out if the old code is busted or just overcomplicated
2702 // but working as intended.
2703
2704 // Look through all new points and see if any are farther than
2705 // acceptable from all previous points.
2706 for (uint32_t i = pointerCount; i-- > 0; ) {
2707 int32_t y = mCurrentTouch.pointers[i].y;
2708 int32_t closestY = INT_MAX;
2709 int32_t closestDeltaY = 0;
2710
2711#if DEBUG_HACKS
2712 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2713#endif
2714
2715 for (uint32_t j = pointerCount; j-- > 0; ) {
2716 int32_t lastY = mLastTouch.pointers[j].y;
2717 int32_t deltaY = abs(y - lastY);
2718
2719#if DEBUG_HACKS
2720 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2721 j, lastY, deltaY);
2722#endif
2723
2724 if (deltaY < maxDeltaY) {
2725 goto SkipSufficientlyClosePoint;
2726 }
2727 if (deltaY < closestDeltaY) {
2728 closestDeltaY = deltaY;
2729 closestY = lastY;
2730 }
2731 }
2732
2733 // Must not have found a close enough match.
2734#if DEBUG_HACKS
2735 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2736 i, y, closestY, closestDeltaY, maxDeltaY);
2737#endif
2738
2739 mCurrentTouch.pointers[i].y = closestY;
2740 return true; // XXX original code only corrects one point
2741
2742 SkipSufficientlyClosePoint: ;
2743 }
2744
2745 // No change.
2746 return false;
2747}
2748
2749/* Special hack for devices that have bad screen data: drop points where
2750 * the coordinate value for one axis has jumped to the other pointer's location.
2751 */
2752bool TouchInputMapper::applyJumpyTouchFilter() {
2753 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002754 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002755 return false;
2756 }
2757
2758 uint32_t pointerCount = mCurrentTouch.pointerCount;
2759 if (mLastTouch.pointerCount != pointerCount) {
2760#if DEBUG_HACKS
2761 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2762 mLastTouch.pointerCount, pointerCount);
2763 for (uint32_t i = 0; i < pointerCount; i++) {
2764 LOGD(" Pointer %d (%d, %d)", i,
2765 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2766 }
2767#endif
2768
2769 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2770 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2771 // Just drop the first few events going from 1 to 2 pointers.
2772 // They're bad often enough that they're not worth considering.
2773 mCurrentTouch.pointerCount = 1;
2774 mJumpyTouchFilter.jumpyPointsDropped += 1;
2775
2776#if DEBUG_HACKS
2777 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2778#endif
2779 return true;
2780 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2781 // The event when we go from 2 -> 1 tends to be messed up too
2782 mCurrentTouch.pointerCount = 2;
2783 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2784 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2785 mJumpyTouchFilter.jumpyPointsDropped += 1;
2786
2787#if DEBUG_HACKS
2788 for (int32_t i = 0; i < 2; i++) {
2789 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2790 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2791 }
2792#endif
2793 return true;
2794 }
2795 }
2796 // Reset jumpy points dropped on other transitions or if limit exceeded.
2797 mJumpyTouchFilter.jumpyPointsDropped = 0;
2798
2799#if DEBUG_HACKS
2800 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2801#endif
2802 return false;
2803 }
2804
2805 // We have the same number of pointers as last time.
2806 // A 'jumpy' point is one where the coordinate value for one axis
2807 // has jumped to the other pointer's location. No need to do anything
2808 // else if we only have one pointer.
2809 if (pointerCount < 2) {
2810 return false;
2811 }
2812
2813 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002814 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002815
2816 // We only replace the single worst jumpy point as characterized by pointer distance
2817 // in a single axis.
2818 int32_t badPointerIndex = -1;
2819 int32_t badPointerReplacementIndex = -1;
2820 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2821
2822 for (uint32_t i = pointerCount; i-- > 0; ) {
2823 int32_t x = mCurrentTouch.pointers[i].x;
2824 int32_t y = mCurrentTouch.pointers[i].y;
2825
2826#if DEBUG_HACKS
2827 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2828#endif
2829
2830 // Check if a touch point is too close to another's coordinates
2831 bool dropX = false, dropY = false;
2832 for (uint32_t j = 0; j < pointerCount; j++) {
2833 if (i == j) {
2834 continue;
2835 }
2836
2837 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2838 dropX = true;
2839 break;
2840 }
2841
2842 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2843 dropY = true;
2844 break;
2845 }
2846 }
2847 if (! dropX && ! dropY) {
2848 continue; // not jumpy
2849 }
2850
2851 // Find a replacement candidate by comparing with older points on the
2852 // complementary (non-jumpy) axis.
2853 int32_t distance = INT_MIN; // distance to be corrected
2854 int32_t replacementIndex = -1;
2855
2856 if (dropX) {
2857 // X looks too close. Find an older replacement point with a close Y.
2858 int32_t smallestDeltaY = INT_MAX;
2859 for (uint32_t j = 0; j < pointerCount; j++) {
2860 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2861 if (deltaY < smallestDeltaY) {
2862 smallestDeltaY = deltaY;
2863 replacementIndex = j;
2864 }
2865 }
2866 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2867 } else {
2868 // Y looks too close. Find an older replacement point with a close X.
2869 int32_t smallestDeltaX = INT_MAX;
2870 for (uint32_t j = 0; j < pointerCount; j++) {
2871 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2872 if (deltaX < smallestDeltaX) {
2873 smallestDeltaX = deltaX;
2874 replacementIndex = j;
2875 }
2876 }
2877 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2878 }
2879
2880 // If replacing this pointer would correct a worse error than the previous ones
2881 // considered, then use this replacement instead.
2882 if (distance > badPointerDistance) {
2883 badPointerIndex = i;
2884 badPointerReplacementIndex = replacementIndex;
2885 badPointerDistance = distance;
2886 }
2887 }
2888
2889 // Correct the jumpy pointer if one was found.
2890 if (badPointerIndex >= 0) {
2891#if DEBUG_HACKS
2892 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2893 badPointerIndex,
2894 mLastTouch.pointers[badPointerReplacementIndex].x,
2895 mLastTouch.pointers[badPointerReplacementIndex].y);
2896#endif
2897
2898 mCurrentTouch.pointers[badPointerIndex].x =
2899 mLastTouch.pointers[badPointerReplacementIndex].x;
2900 mCurrentTouch.pointers[badPointerIndex].y =
2901 mLastTouch.pointers[badPointerReplacementIndex].y;
2902 mJumpyTouchFilter.jumpyPointsDropped += 1;
2903 return true;
2904 }
2905 }
2906
2907 mJumpyTouchFilter.jumpyPointsDropped = 0;
2908 return false;
2909}
2910
2911/* Special hack for devices that have bad screen data: aggregate and
2912 * compute averages of the coordinate data, to reduce the amount of
2913 * jitter seen by applications. */
2914void TouchInputMapper::applyAveragingTouchFilter() {
2915 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2916 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2917 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2918 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002919 int32_t pressure;
2920 switch (mCalibration.pressureSource) {
2921 case Calibration::PRESSURE_SOURCE_PRESSURE:
2922 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2923 break;
2924 case Calibration::PRESSURE_SOURCE_TOUCH:
2925 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2926 break;
2927 default:
2928 pressure = 1;
2929 break;
2930 }
Jeff Browne57e8952010-07-23 21:28:06 -07002931
2932 if (mLastTouch.idBits.hasBit(id)) {
2933 // Pointer was down before and is still down now.
2934 // Compute average over history trace.
2935 uint32_t start = mAveragingTouchFilter.historyStart[id];
2936 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2937
2938 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2939 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2940 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2941
2942#if DEBUG_HACKS
2943 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2944 id, distance);
2945#endif
2946
2947 if (distance < AVERAGING_DISTANCE_LIMIT) {
2948 // Increment end index in preparation for recording new historical data.
2949 end += 1;
2950 if (end > AVERAGING_HISTORY_SIZE) {
2951 end = 0;
2952 }
2953
2954 // If the end index has looped back to the start index then we have filled
2955 // the historical trace up to the desired size so we drop the historical
2956 // data at the start of the trace.
2957 if (end == start) {
2958 start += 1;
2959 if (start > AVERAGING_HISTORY_SIZE) {
2960 start = 0;
2961 }
2962 }
2963
2964 // Add the raw data to the historical trace.
2965 mAveragingTouchFilter.historyStart[id] = start;
2966 mAveragingTouchFilter.historyEnd[id] = end;
2967 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2968 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2969 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2970
2971 // Average over all historical positions in the trace by total pressure.
2972 int32_t averagedX = 0;
2973 int32_t averagedY = 0;
2974 int32_t totalPressure = 0;
2975 for (;;) {
2976 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2977 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2978 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2979 .pointers[id].pressure;
2980
2981 averagedX += historicalX * historicalPressure;
2982 averagedY += historicalY * historicalPressure;
2983 totalPressure += historicalPressure;
2984
2985 if (start == end) {
2986 break;
2987 }
2988
2989 start += 1;
2990 if (start > AVERAGING_HISTORY_SIZE) {
2991 start = 0;
2992 }
2993 }
2994
Jeff Brown38a7fab2010-08-30 03:02:23 -07002995 if (totalPressure != 0) {
2996 averagedX /= totalPressure;
2997 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07002998
2999#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07003000 LOGD("AveragingTouchFilter: Pointer id %d - "
3001 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3002 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07003003#endif
3004
Jeff Brown38a7fab2010-08-30 03:02:23 -07003005 mCurrentTouch.pointers[currentIndex].x = averagedX;
3006 mCurrentTouch.pointers[currentIndex].y = averagedY;
3007 }
Jeff Browne57e8952010-07-23 21:28:06 -07003008 } else {
3009#if DEBUG_HACKS
3010 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3011#endif
3012 }
3013 } else {
3014#if DEBUG_HACKS
3015 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3016#endif
3017 }
3018
3019 // Reset pointer history.
3020 mAveragingTouchFilter.historyStart[id] = 0;
3021 mAveragingTouchFilter.historyEnd[id] = 0;
3022 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3023 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3024 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3025 }
3026}
3027
3028int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003029 { // acquire lock
3030 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003031
Jeff Brownb51719b2010-07-29 18:18:33 -07003032 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003033 return AKEY_STATE_VIRTUAL;
3034 }
3035
Jeff Brownb51719b2010-07-29 18:18:33 -07003036 size_t numVirtualKeys = mLocked.virtualKeys.size();
3037 for (size_t i = 0; i < numVirtualKeys; i++) {
3038 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003039 if (virtualKey.keyCode == keyCode) {
3040 return AKEY_STATE_UP;
3041 }
3042 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003043 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003044
3045 return AKEY_STATE_UNKNOWN;
3046}
3047
3048int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003049 { // acquire lock
3050 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003051
Jeff Brownb51719b2010-07-29 18:18:33 -07003052 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003053 return AKEY_STATE_VIRTUAL;
3054 }
3055
Jeff Brownb51719b2010-07-29 18:18:33 -07003056 size_t numVirtualKeys = mLocked.virtualKeys.size();
3057 for (size_t i = 0; i < numVirtualKeys; i++) {
3058 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003059 if (virtualKey.scanCode == scanCode) {
3060 return AKEY_STATE_UP;
3061 }
3062 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003063 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003064
3065 return AKEY_STATE_UNKNOWN;
3066}
3067
3068bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3069 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003070 { // acquire lock
3071 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003072
Jeff Brownb51719b2010-07-29 18:18:33 -07003073 size_t numVirtualKeys = mLocked.virtualKeys.size();
3074 for (size_t i = 0; i < numVirtualKeys; i++) {
3075 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003076
3077 for (size_t i = 0; i < numCodes; i++) {
3078 if (virtualKey.keyCode == keyCodes[i]) {
3079 outFlags[i] = 1;
3080 }
3081 }
3082 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003083 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003084
3085 return true;
3086}
3087
3088
3089// --- SingleTouchInputMapper ---
3090
3091SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3092 TouchInputMapper(device, associatedDisplayId) {
3093 initialize();
3094}
3095
3096SingleTouchInputMapper::~SingleTouchInputMapper() {
3097}
3098
3099void SingleTouchInputMapper::initialize() {
3100 mAccumulator.clear();
3101
3102 mDown = false;
3103 mX = 0;
3104 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003105 mPressure = 0; // default to 0 for devices that don't report pressure
3106 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003107}
3108
3109void SingleTouchInputMapper::reset() {
3110 TouchInputMapper::reset();
3111
Jeff Browne57e8952010-07-23 21:28:06 -07003112 initialize();
3113 }
3114
3115void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3116 switch (rawEvent->type) {
3117 case EV_KEY:
3118 switch (rawEvent->scanCode) {
3119 case BTN_TOUCH:
3120 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3121 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003122 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3123 // not have received valid position information yet. This logic assumes that
3124 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003125 break;
3126 }
3127 break;
3128
3129 case EV_ABS:
3130 switch (rawEvent->scanCode) {
3131 case ABS_X:
3132 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3133 mAccumulator.absX = rawEvent->value;
3134 break;
3135 case ABS_Y:
3136 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3137 mAccumulator.absY = rawEvent->value;
3138 break;
3139 case ABS_PRESSURE:
3140 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3141 mAccumulator.absPressure = rawEvent->value;
3142 break;
3143 case ABS_TOOL_WIDTH:
3144 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3145 mAccumulator.absToolWidth = rawEvent->value;
3146 break;
3147 }
3148 break;
3149
3150 case EV_SYN:
3151 switch (rawEvent->scanCode) {
3152 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003153 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003154 break;
3155 }
3156 break;
3157 }
3158}
3159
3160void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003161 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003162 if (fields == 0) {
3163 return; // no new state changes, so nothing to do
3164 }
Jeff Browne57e8952010-07-23 21:28:06 -07003165
3166 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3167 mDown = mAccumulator.btnTouch;
3168 }
3169
3170 if (fields & Accumulator::FIELD_ABS_X) {
3171 mX = mAccumulator.absX;
3172 }
3173
3174 if (fields & Accumulator::FIELD_ABS_Y) {
3175 mY = mAccumulator.absY;
3176 }
3177
3178 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3179 mPressure = mAccumulator.absPressure;
3180 }
3181
3182 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003183 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003184 }
3185
3186 mCurrentTouch.clear();
3187
3188 if (mDown) {
3189 mCurrentTouch.pointerCount = 1;
3190 mCurrentTouch.pointers[0].id = 0;
3191 mCurrentTouch.pointers[0].x = mX;
3192 mCurrentTouch.pointers[0].y = mY;
3193 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003194 mCurrentTouch.pointers[0].touchMajor = 0;
3195 mCurrentTouch.pointers[0].touchMinor = 0;
3196 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3197 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003198 mCurrentTouch.pointers[0].orientation = 0;
3199 mCurrentTouch.idToIndex[0] = 0;
3200 mCurrentTouch.idBits.markBit(0);
3201 }
3202
3203 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003204
3205 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003206}
3207
Jeff Brown38a7fab2010-08-30 03:02:23 -07003208void SingleTouchInputMapper::configureRawAxes() {
3209 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003210
Jeff Brown38a7fab2010-08-30 03:02:23 -07003211 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3212 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3213 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3214 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003215}
3216
3217
3218// --- MultiTouchInputMapper ---
3219
3220MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3221 TouchInputMapper(device, associatedDisplayId) {
3222 initialize();
3223}
3224
3225MultiTouchInputMapper::~MultiTouchInputMapper() {
3226}
3227
3228void MultiTouchInputMapper::initialize() {
3229 mAccumulator.clear();
3230}
3231
3232void MultiTouchInputMapper::reset() {
3233 TouchInputMapper::reset();
3234
Jeff Browne57e8952010-07-23 21:28:06 -07003235 initialize();
3236}
3237
3238void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3239 switch (rawEvent->type) {
3240 case EV_ABS: {
3241 uint32_t pointerIndex = mAccumulator.pointerCount;
3242 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3243
3244 switch (rawEvent->scanCode) {
3245 case ABS_MT_POSITION_X:
3246 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3247 pointer->absMTPositionX = rawEvent->value;
3248 break;
3249 case ABS_MT_POSITION_Y:
3250 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3251 pointer->absMTPositionY = rawEvent->value;
3252 break;
3253 case ABS_MT_TOUCH_MAJOR:
3254 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3255 pointer->absMTTouchMajor = rawEvent->value;
3256 break;
3257 case ABS_MT_TOUCH_MINOR:
3258 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3259 pointer->absMTTouchMinor = rawEvent->value;
3260 break;
3261 case ABS_MT_WIDTH_MAJOR:
3262 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3263 pointer->absMTWidthMajor = rawEvent->value;
3264 break;
3265 case ABS_MT_WIDTH_MINOR:
3266 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3267 pointer->absMTWidthMinor = rawEvent->value;
3268 break;
3269 case ABS_MT_ORIENTATION:
3270 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3271 pointer->absMTOrientation = rawEvent->value;
3272 break;
3273 case ABS_MT_TRACKING_ID:
3274 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3275 pointer->absMTTrackingId = rawEvent->value;
3276 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003277 case ABS_MT_PRESSURE:
3278 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3279 pointer->absMTPressure = rawEvent->value;
3280 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003281 }
3282 break;
3283 }
3284
3285 case EV_SYN:
3286 switch (rawEvent->scanCode) {
3287 case SYN_MT_REPORT: {
3288 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3289 uint32_t pointerIndex = mAccumulator.pointerCount;
3290
3291 if (mAccumulator.pointers[pointerIndex].fields) {
3292 if (pointerIndex == MAX_POINTERS) {
3293 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3294 MAX_POINTERS);
3295 } else {
3296 pointerIndex += 1;
3297 mAccumulator.pointerCount = pointerIndex;
3298 }
3299 }
3300
3301 mAccumulator.pointers[pointerIndex].clear();
3302 break;
3303 }
3304
3305 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003306 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003307 break;
3308 }
3309 break;
3310 }
3311}
3312
3313void MultiTouchInputMapper::sync(nsecs_t when) {
3314 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003315 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003316
Jeff Browne57e8952010-07-23 21:28:06 -07003317 uint32_t inCount = mAccumulator.pointerCount;
3318 uint32_t outCount = 0;
3319 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003320
Jeff Browne57e8952010-07-23 21:28:06 -07003321 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003322
Jeff Browne57e8952010-07-23 21:28:06 -07003323 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003324 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3325 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003326
Jeff Browne57e8952010-07-23 21:28:06 -07003327 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003328 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3329 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003330 continue;
3331 }
3332
Jeff Brownd64c8552010-08-17 20:38:35 -07003333 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3334 outPointer.x = inPointer.absMTPositionX;
3335 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003336
Jeff Brown38a7fab2010-08-30 03:02:23 -07003337 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3338 if (inPointer.absMTPressure <= 0) {
3339 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brownd64c8552010-08-17 20:38:35 -07003340 // a pointer up. Drop this finger.
3341 continue;
3342 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003343 outPointer.pressure = inPointer.absMTPressure;
3344 } else {
3345 // Default pressure to 0 if absent.
3346 outPointer.pressure = 0;
3347 }
3348
3349 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3350 if (inPointer.absMTTouchMajor <= 0) {
3351 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3352 // a pointer going up. Drop this finger.
3353 continue;
3354 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003355 outPointer.touchMajor = inPointer.absMTTouchMajor;
3356 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003357 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003358 outPointer.touchMajor = 0;
3359 }
Jeff Browne839a582010-04-22 18:58:52 -07003360
Jeff Brownd64c8552010-08-17 20:38:35 -07003361 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3362 outPointer.touchMinor = inPointer.absMTTouchMinor;
3363 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003364 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003365 outPointer.touchMinor = outPointer.touchMajor;
3366 }
Jeff Browne839a582010-04-22 18:58:52 -07003367
Jeff Brownd64c8552010-08-17 20:38:35 -07003368 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3369 outPointer.toolMajor = inPointer.absMTWidthMajor;
3370 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003371 // Default tool area to 0 if absent.
3372 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003373 }
Jeff Browne839a582010-04-22 18:58:52 -07003374
Jeff Brownd64c8552010-08-17 20:38:35 -07003375 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3376 outPointer.toolMinor = inPointer.absMTWidthMinor;
3377 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003378 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003379 outPointer.toolMinor = outPointer.toolMajor;
3380 }
3381
3382 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3383 outPointer.orientation = inPointer.absMTOrientation;
3384 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003385 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003386 outPointer.orientation = 0;
3387 }
3388
Jeff Brown38a7fab2010-08-30 03:02:23 -07003389 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003390 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003391 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3392 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003393
Jeff Browne57e8952010-07-23 21:28:06 -07003394 if (id > MAX_POINTER_ID) {
3395#if DEBUG_POINTERS
3396 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003397 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003398 id, MAX_POINTER_ID);
3399#endif
3400 havePointerIds = false;
3401 }
3402 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003403 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003404 mCurrentTouch.idToIndex[id] = outCount;
3405 mCurrentTouch.idBits.markBit(id);
3406 }
3407 } else {
3408 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003409 }
3410 }
Jeff Browne839a582010-04-22 18:58:52 -07003411
Jeff Browne57e8952010-07-23 21:28:06 -07003412 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003413 }
3414
Jeff Browne57e8952010-07-23 21:28:06 -07003415 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003416
Jeff Browne57e8952010-07-23 21:28:06 -07003417 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003418
3419 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003420}
3421
Jeff Brown38a7fab2010-08-30 03:02:23 -07003422void MultiTouchInputMapper::configureRawAxes() {
3423 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003424
Jeff Brown38a7fab2010-08-30 03:02:23 -07003425 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3426 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3427 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3428 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3429 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3430 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3431 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3432 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003433}
3434
Jeff Browne839a582010-04-22 18:58:52 -07003435
3436} // namespace android