blob: ea05f5c3fe092ac318affef74e68e05e74a3dfeb [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brownf4a4ec22010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Browne839a582010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
Jeff Brown38a7fab2010-08-30 03:02:23 -070029#include <stdlib.h>
Jeff Browne839a582010-04-22 18:58:52 -070030#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070031#include <errno.h>
32#include <limits.h>
Jeff Brown5c1ed842010-07-14 18:48:53 -070033#include <math.h>
Jeff Browne839a582010-04-22 18:58:52 -070034
Jeff Brown38a7fab2010-08-30 03:02:23 -070035#define INDENT " "
Jeff Brown26c94ff2010-09-30 14:33:04 -070036#define INDENT2 " "
37#define INDENT3 " "
38#define INDENT4 " "
Jeff Brown38a7fab2010-08-30 03:02:23 -070039
Jeff Browne839a582010-04-22 18:58:52 -070040namespace android {
41
42// --- Static Functions ---
43
44template<typename T>
45inline static T abs(const T& value) {
46 return value < 0 ? - value : value;
47}
48
49template<typename T>
50inline static T min(const T& a, const T& b) {
51 return a < b ? a : b;
52}
53
Jeff Brownf4a4ec22010-06-16 01:53:36 -070054template<typename T>
55inline static void swap(T& a, T& b) {
56 T temp = a;
57 a = b;
58 b = temp;
59}
60
Jeff Brown38a7fab2010-08-30 03:02:23 -070061inline static float avg(float x, float y) {
62 return (x + y) / 2;
63}
64
65inline static float pythag(float x, float y) {
66 return sqrtf(x * x + y * y);
67}
68
Jeff Brown26c94ff2010-09-30 14:33:04 -070069static inline const char* toString(bool value) {
70 return value ? "true" : "false";
71}
72
Jeff Brownf4a4ec22010-06-16 01:53:36 -070073
Jeff Browne839a582010-04-22 18:58:52 -070074int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
75 int32_t mask;
76 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070077 case AKEYCODE_ALT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070078 mask = AMETA_ALT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070079 break;
Jeff Brown8575a872010-06-30 16:10:35 -070080 case AKEYCODE_ALT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070081 mask = AMETA_ALT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070082 break;
Jeff Brown8575a872010-06-30 16:10:35 -070083 case AKEYCODE_SHIFT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070084 mask = AMETA_SHIFT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070085 break;
Jeff Brown8575a872010-06-30 16:10:35 -070086 case AKEYCODE_SHIFT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070087 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070088 break;
Jeff Brown8575a872010-06-30 16:10:35 -070089 case AKEYCODE_SYM:
Jeff Brown5c1ed842010-07-14 18:48:53 -070090 mask = AMETA_SYM_ON;
Jeff Browne839a582010-04-22 18:58:52 -070091 break;
92 default:
93 return oldMetaState;
94 }
95
96 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brown5c1ed842010-07-14 18:48:53 -070097 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Browne839a582010-04-22 18:58:52 -070098
Jeff Brown5c1ed842010-07-14 18:48:53 -070099 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
100 newMetaState |= AMETA_ALT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700101 }
102
Jeff Brown5c1ed842010-07-14 18:48:53 -0700103 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
104 newMetaState |= AMETA_SHIFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700105 }
106
107 return newMetaState;
108}
109
110static const int32_t keyCodeRotationMap[][4] = {
111 // key codes enumerated counter-clockwise with the original (unrotated) key first
112 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brown8575a872010-06-30 16:10:35 -0700113 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
114 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
115 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
116 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Browne839a582010-04-22 18:58:52 -0700117};
118static const int keyCodeRotationMapSize =
119 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
120
121int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700122 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-04-22 18:58:52 -0700123 for (int i = 0; i < keyCodeRotationMapSize; i++) {
124 if (keyCode == keyCodeRotationMap[i][0]) {
125 return keyCodeRotationMap[i][orientation];
126 }
127 }
128 }
129 return keyCode;
130}
131
Jeff Browne57e8952010-07-23 21:28:06 -0700132static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
133 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
134}
135
Jeff Browne839a582010-04-22 18:58:52 -0700136
Jeff Brown38a7fab2010-08-30 03:02:23 -0700137// --- InputDeviceCalibration ---
138
139InputDeviceCalibration::InputDeviceCalibration() {
140}
141
142void InputDeviceCalibration::clear() {
143 mProperties.clear();
144}
145
146void InputDeviceCalibration::addProperty(const String8& key, const String8& value) {
147 mProperties.add(key, value);
148}
149
150bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const {
151 ssize_t index = mProperties.indexOfKey(key);
152 if (index < 0) {
153 return false;
154 }
155
156 outValue = mProperties.valueAt(index);
157 return true;
158}
159
160bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const {
161 String8 stringValue;
162 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
163 return false;
164 }
165
166 char* end;
167 int value = strtol(stringValue.string(), & end, 10);
168 if (*end != '\0') {
169 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.",
170 key.string(), stringValue.string());
171 return false;
172 }
173 outValue = value;
174 return true;
175}
176
177bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const {
178 String8 stringValue;
179 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
180 return false;
181 }
182
183 char* end;
184 float value = strtof(stringValue.string(), & end);
185 if (*end != '\0') {
186 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.",
187 key.string(), stringValue.string());
188 return false;
189 }
190 outValue = value;
191 return true;
192}
193
194
Jeff Browne839a582010-04-22 18:58:52 -0700195// --- InputReader ---
196
197InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700198 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700199 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Browne57e8952010-07-23 21:28:06 -0700200 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
201 mGlobalMetaState(0) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700202 configureExcludedDevices();
Jeff Browne57e8952010-07-23 21:28:06 -0700203 updateGlobalMetaState();
204 updateInputConfiguration();
Jeff Browne839a582010-04-22 18:58:52 -0700205}
206
207InputReader::~InputReader() {
208 for (size_t i = 0; i < mDevices.size(); i++) {
209 delete mDevices.valueAt(i);
210 }
211}
212
213void InputReader::loopOnce() {
214 RawEvent rawEvent;
Jeff Browne57e8952010-07-23 21:28:06 -0700215 mEventHub->getEvent(& rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700216
217#if DEBUG_RAW_EVENTS
218 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
219 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
220 rawEvent.value);
221#endif
222
223 process(& rawEvent);
224}
225
226void InputReader::process(const RawEvent* rawEvent) {
227 switch (rawEvent->type) {
228 case EventHubInterface::DEVICE_ADDED:
Jeff Browne57e8952010-07-23 21:28:06 -0700229 addDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700230 break;
231
232 case EventHubInterface::DEVICE_REMOVED:
Jeff Browne57e8952010-07-23 21:28:06 -0700233 removeDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700234 break;
235
Jeff Browne57e8952010-07-23 21:28:06 -0700236 default:
237 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700238 break;
239 }
240}
241
Jeff Browne57e8952010-07-23 21:28:06 -0700242void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
243 String8 name = mEventHub->getDeviceName(deviceId);
244 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
245
246 InputDevice* device = createDevice(deviceId, name, classes);
247 device->configure();
248
Jeff Brown38a7fab2010-08-30 03:02:23 -0700249 if (device->isIgnored()) {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700250 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", deviceId, name.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700251 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700252 LOGI("Device added: id=0x%x, name=%s, sources=%08x", deviceId, name.string(),
253 device->getSources());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700254 }
255
Jeff Browne57e8952010-07-23 21:28:06 -0700256 bool added = false;
257 { // acquire device registry writer lock
258 RWLock::AutoWLock _wl(mDeviceRegistryLock);
259
260 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
261 if (deviceIndex < 0) {
262 mDevices.add(deviceId, device);
263 added = true;
264 }
265 } // release device registry writer lock
266
267 if (! added) {
268 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
269 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700270 return;
271 }
272
Jeff Browne57e8952010-07-23 21:28:06 -0700273 handleConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700274}
275
Jeff Browne57e8952010-07-23 21:28:06 -0700276void InputReader::removeDevice(nsecs_t when, int32_t deviceId) {
277 bool removed = false;
278 InputDevice* device = NULL;
279 { // acquire device registry writer lock
280 RWLock::AutoWLock _wl(mDeviceRegistryLock);
281
282 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
283 if (deviceIndex >= 0) {
284 device = mDevices.valueAt(deviceIndex);
285 mDevices.removeItemsAt(deviceIndex, 1);
286 removed = true;
287 }
288 } // release device registry writer lock
289
290 if (! removed) {
291 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700292 return;
293 }
294
Jeff Browne57e8952010-07-23 21:28:06 -0700295 if (device->isIgnored()) {
296 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
297 device->getId(), device->getName().string());
298 } else {
299 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
300 device->getId(), device->getName().string(), device->getSources());
301 }
302
Jeff Brown38a7fab2010-08-30 03:02:23 -0700303 device->reset();
304
Jeff Browne57e8952010-07-23 21:28:06 -0700305 delete device;
306
307 handleConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700308}
309
Jeff Browne57e8952010-07-23 21:28:06 -0700310InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
311 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Browne839a582010-04-22 18:58:52 -0700312
Jeff Browne57e8952010-07-23 21:28:06 -0700313 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Browne839a582010-04-22 18:58:52 -0700314
Jeff Browne57e8952010-07-23 21:28:06 -0700315 // Switch-like devices.
316 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
317 device->addMapper(new SwitchInputMapper(device));
318 }
319
320 // Keyboard-like devices.
321 uint32_t keyboardSources = 0;
322 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
323 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
324 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
325 }
326 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
327 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
328 }
329 if (classes & INPUT_DEVICE_CLASS_DPAD) {
330 keyboardSources |= AINPUT_SOURCE_DPAD;
331 }
Jeff Browne57e8952010-07-23 21:28:06 -0700332
333 if (keyboardSources != 0) {
334 device->addMapper(new KeyboardInputMapper(device,
335 associatedDisplayId, keyboardSources, keyboardType));
336 }
337
338 // Trackball-like devices.
339 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
340 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
341 }
342
343 // Touchscreen-like devices.
344 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
345 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
346 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
347 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
348 }
349
350 return device;
351}
352
353void InputReader::consumeEvent(const RawEvent* rawEvent) {
354 int32_t deviceId = rawEvent->deviceId;
355
356 { // acquire device registry reader lock
357 RWLock::AutoRLock _rl(mDeviceRegistryLock);
358
359 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
360 if (deviceIndex < 0) {
361 LOGW("Discarding event for unknown deviceId %d.", deviceId);
362 return;
363 }
364
365 InputDevice* device = mDevices.valueAt(deviceIndex);
366 if (device->isIgnored()) {
367 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
368 return;
369 }
370
371 device->process(rawEvent);
372 } // release device registry reader lock
373}
374
375void InputReader::handleConfigurationChanged(nsecs_t when) {
376 // Reset global meta state because it depends on the list of all configured devices.
377 updateGlobalMetaState();
378
379 // Update input configuration.
380 updateInputConfiguration();
381
382 // Enqueue configuration changed.
383 mDispatcher->notifyConfigurationChanged(when);
384}
385
386void InputReader::configureExcludedDevices() {
387 Vector<String8> excludedDeviceNames;
388 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
389
390 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
391 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
392 }
393}
394
395void InputReader::updateGlobalMetaState() {
396 { // acquire state lock
397 AutoMutex _l(mStateLock);
398
399 mGlobalMetaState = 0;
400
401 { // acquire device registry reader lock
402 RWLock::AutoRLock _rl(mDeviceRegistryLock);
403
404 for (size_t i = 0; i < mDevices.size(); i++) {
405 InputDevice* device = mDevices.valueAt(i);
406 mGlobalMetaState |= device->getMetaState();
407 }
408 } // release device registry reader lock
409 } // release state lock
410}
411
412int32_t InputReader::getGlobalMetaState() {
413 { // acquire state lock
414 AutoMutex _l(mStateLock);
415
416 return mGlobalMetaState;
417 } // release state lock
418}
419
420void InputReader::updateInputConfiguration() {
421 { // acquire state lock
422 AutoMutex _l(mStateLock);
423
424 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
425 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
426 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
427 { // acquire device registry reader lock
428 RWLock::AutoRLock _rl(mDeviceRegistryLock);
429
430 InputDeviceInfo deviceInfo;
431 for (size_t i = 0; i < mDevices.size(); i++) {
432 InputDevice* device = mDevices.valueAt(i);
433 device->getDeviceInfo(& deviceInfo);
434 uint32_t sources = deviceInfo.getSources();
435
436 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
437 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
438 }
439 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
440 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
441 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
442 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
443 }
444 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
445 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Browne839a582010-04-22 18:58:52 -0700446 }
447 }
Jeff Browne57e8952010-07-23 21:28:06 -0700448 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700449
Jeff Browne57e8952010-07-23 21:28:06 -0700450 mInputConfiguration.touchScreen = touchScreenConfig;
451 mInputConfiguration.keyboard = keyboardConfig;
452 mInputConfiguration.navigation = navigationConfig;
453 } // release state lock
454}
455
456void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
457 { // acquire state lock
458 AutoMutex _l(mStateLock);
459
460 *outConfiguration = mInputConfiguration;
461 } // release state lock
462}
463
464status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
465 { // acquire device registry reader lock
466 RWLock::AutoRLock _rl(mDeviceRegistryLock);
467
468 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
469 if (deviceIndex < 0) {
470 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700471 }
472
Jeff Browne57e8952010-07-23 21:28:06 -0700473 InputDevice* device = mDevices.valueAt(deviceIndex);
474 if (device->isIgnored()) {
475 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700476 }
Jeff Browne57e8952010-07-23 21:28:06 -0700477
478 device->getDeviceInfo(outDeviceInfo);
479 return OK;
480 } // release device registy reader lock
481}
482
483void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
484 outDeviceIds.clear();
485
486 { // acquire device registry reader lock
487 RWLock::AutoRLock _rl(mDeviceRegistryLock);
488
489 size_t numDevices = mDevices.size();
490 for (size_t i = 0; i < numDevices; i++) {
491 InputDevice* device = mDevices.valueAt(i);
492 if (! device->isIgnored()) {
493 outDeviceIds.add(device->getId());
494 }
495 }
496 } // release device registy reader lock
497}
498
499int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
500 int32_t keyCode) {
501 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
502}
503
504int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
505 int32_t scanCode) {
506 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
507}
508
509int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
510 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
511}
512
513int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
514 GetStateFunc getStateFunc) {
515 { // acquire device registry reader lock
516 RWLock::AutoRLock _rl(mDeviceRegistryLock);
517
518 int32_t result = AKEY_STATE_UNKNOWN;
519 if (deviceId >= 0) {
520 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
521 if (deviceIndex >= 0) {
522 InputDevice* device = mDevices.valueAt(deviceIndex);
523 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
524 result = (device->*getStateFunc)(sourceMask, code);
525 }
526 }
527 } else {
528 size_t numDevices = mDevices.size();
529 for (size_t i = 0; i < numDevices; i++) {
530 InputDevice* device = mDevices.valueAt(i);
531 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
532 result = (device->*getStateFunc)(sourceMask, code);
533 if (result >= AKEY_STATE_DOWN) {
534 return result;
535 }
536 }
537 }
538 }
539 return result;
540 } // release device registy reader lock
541}
542
543bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
544 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
545 memset(outFlags, 0, numCodes);
546 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
547}
548
549bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
550 const int32_t* keyCodes, uint8_t* outFlags) {
551 { // acquire device registry reader lock
552 RWLock::AutoRLock _rl(mDeviceRegistryLock);
553 bool result = false;
554 if (deviceId >= 0) {
555 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
556 if (deviceIndex >= 0) {
557 InputDevice* device = mDevices.valueAt(deviceIndex);
558 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
559 result = device->markSupportedKeyCodes(sourceMask,
560 numCodes, keyCodes, outFlags);
561 }
562 }
563 } else {
564 size_t numDevices = mDevices.size();
565 for (size_t i = 0; i < numDevices; i++) {
566 InputDevice* device = mDevices.valueAt(i);
567 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
568 result |= device->markSupportedKeyCodes(sourceMask,
569 numCodes, keyCodes, outFlags);
570 }
571 }
572 }
573 return result;
574 } // release device registy reader lock
575}
576
Jeff Browna665ca82010-09-08 11:49:43 -0700577void InputReader::dump(String8& dump) {
Jeff Brown2806e382010-10-01 17:46:21 -0700578 mEventHub->dump(dump);
579 dump.append("\n");
580
581 dump.append("Input Reader State:\n");
582
Jeff Brown26c94ff2010-09-30 14:33:04 -0700583 { // acquire device registry reader lock
584 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Browna665ca82010-09-08 11:49:43 -0700585
Jeff Brown26c94ff2010-09-30 14:33:04 -0700586 for (size_t i = 0; i < mDevices.size(); i++) {
587 mDevices.valueAt(i)->dump(dump);
Jeff Browna665ca82010-09-08 11:49:43 -0700588 }
Jeff Brown26c94ff2010-09-30 14:33:04 -0700589 } // release device registy reader lock
Jeff Browna665ca82010-09-08 11:49:43 -0700590}
591
Jeff Browne57e8952010-07-23 21:28:06 -0700592
593// --- InputReaderThread ---
594
595InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
596 Thread(/*canCallJava*/ true), mReader(reader) {
597}
598
599InputReaderThread::~InputReaderThread() {
600}
601
602bool InputReaderThread::threadLoop() {
603 mReader->loopOnce();
604 return true;
605}
606
607
608// --- InputDevice ---
609
610InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
611 mContext(context), mId(id), mName(name), mSources(0) {
612}
613
614InputDevice::~InputDevice() {
615 size_t numMappers = mMappers.size();
616 for (size_t i = 0; i < numMappers; i++) {
617 delete mMappers[i];
618 }
619 mMappers.clear();
620}
621
Jeff Brown26c94ff2010-09-30 14:33:04 -0700622static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
623 int32_t rangeType, const char* name) {
624 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
625 if (range) {
626 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
627 name, range->min, range->max, range->flat, range->fuzz);
628 }
629}
630
631void InputDevice::dump(String8& dump) {
632 InputDeviceInfo deviceInfo;
633 getDeviceInfo(& deviceInfo);
634
635 dump.appendFormat(INDENT "Device 0x%x: %s\n", deviceInfo.getId(),
636 deviceInfo.getName().string());
637 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
638 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
639 if (!deviceInfo.getMotionRanges().isEmpty()) {
640 dump.append(INDENT2 "Motion Ranges:\n");
641 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
642 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
643 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
644 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
645 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
646 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
647 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
648 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
649 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
650 }
651
652 size_t numMappers = mMappers.size();
653 for (size_t i = 0; i < numMappers; i++) {
654 InputMapper* mapper = mMappers[i];
655 mapper->dump(dump);
656 }
657}
658
Jeff Browne57e8952010-07-23 21:28:06 -0700659void InputDevice::addMapper(InputMapper* mapper) {
660 mMappers.add(mapper);
661}
662
663void InputDevice::configure() {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700664 if (! isIgnored()) {
665 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
666 }
667
Jeff Browne57e8952010-07-23 21:28:06 -0700668 mSources = 0;
669
670 size_t numMappers = mMappers.size();
671 for (size_t i = 0; i < numMappers; i++) {
672 InputMapper* mapper = mMappers[i];
673 mapper->configure();
674 mSources |= mapper->getSources();
Jeff Browne839a582010-04-22 18:58:52 -0700675 }
676}
677
Jeff Browne57e8952010-07-23 21:28:06 -0700678void InputDevice::reset() {
679 size_t numMappers = mMappers.size();
680 for (size_t i = 0; i < numMappers; i++) {
681 InputMapper* mapper = mMappers[i];
682 mapper->reset();
683 }
684}
Jeff Browne839a582010-04-22 18:58:52 -0700685
Jeff Browne57e8952010-07-23 21:28:06 -0700686void InputDevice::process(const RawEvent* rawEvent) {
687 size_t numMappers = mMappers.size();
688 for (size_t i = 0; i < numMappers; i++) {
689 InputMapper* mapper = mMappers[i];
690 mapper->process(rawEvent);
691 }
692}
Jeff Browne839a582010-04-22 18:58:52 -0700693
Jeff Browne57e8952010-07-23 21:28:06 -0700694void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
695 outDeviceInfo->initialize(mId, mName);
696
697 size_t numMappers = mMappers.size();
698 for (size_t i = 0; i < numMappers; i++) {
699 InputMapper* mapper = mMappers[i];
700 mapper->populateDeviceInfo(outDeviceInfo);
701 }
702}
703
704int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
705 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
706}
707
708int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
709 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
710}
711
712int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
713 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
714}
715
716int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
717 int32_t result = AKEY_STATE_UNKNOWN;
718 size_t numMappers = mMappers.size();
719 for (size_t i = 0; i < numMappers; i++) {
720 InputMapper* mapper = mMappers[i];
721 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
722 result = (mapper->*getStateFunc)(sourceMask, code);
723 if (result >= AKEY_STATE_DOWN) {
724 return result;
725 }
726 }
727 }
728 return result;
729}
730
731bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
732 const int32_t* keyCodes, uint8_t* outFlags) {
733 bool result = false;
734 size_t numMappers = mMappers.size();
735 for (size_t i = 0; i < numMappers; i++) {
736 InputMapper* mapper = mMappers[i];
737 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
738 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
739 }
740 }
741 return result;
742}
743
744int32_t InputDevice::getMetaState() {
745 int32_t result = 0;
746 size_t numMappers = mMappers.size();
747 for (size_t i = 0; i < numMappers; i++) {
748 InputMapper* mapper = mMappers[i];
749 result |= mapper->getMetaState();
750 }
751 return result;
752}
753
754
755// --- InputMapper ---
756
757InputMapper::InputMapper(InputDevice* device) :
758 mDevice(device), mContext(device->getContext()) {
759}
760
761InputMapper::~InputMapper() {
762}
763
764void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
765 info->addSource(getSources());
766}
767
Jeff Brown26c94ff2010-09-30 14:33:04 -0700768void InputMapper::dump(String8& dump) {
769}
770
Jeff Browne57e8952010-07-23 21:28:06 -0700771void InputMapper::configure() {
772}
773
774void InputMapper::reset() {
775}
776
777int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
778 return AKEY_STATE_UNKNOWN;
779}
780
781int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
782 return AKEY_STATE_UNKNOWN;
783}
784
785int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
786 return AKEY_STATE_UNKNOWN;
787}
788
789bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
790 const int32_t* keyCodes, uint8_t* outFlags) {
791 return false;
792}
793
794int32_t InputMapper::getMetaState() {
795 return 0;
796}
797
798bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
Jeff Browne57e8952010-07-23 21:28:06 -0700799 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
800}
801
802
803// --- SwitchInputMapper ---
804
805SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
806 InputMapper(device) {
807}
808
809SwitchInputMapper::~SwitchInputMapper() {
810}
811
812uint32_t SwitchInputMapper::getSources() {
813 return 0;
814}
815
816void SwitchInputMapper::process(const RawEvent* rawEvent) {
817 switch (rawEvent->type) {
818 case EV_SW:
819 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
820 break;
821 }
822}
823
824void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
825 uint32_t policyFlags = 0;
826 int32_t policyActions = getPolicy()->interceptSwitch(
827 when, switchCode, switchValue, policyFlags);
828
829 applyStandardPolicyActions(when, policyActions);
830}
831
832int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
833 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
834}
835
836
837// --- KeyboardInputMapper ---
838
839KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
840 uint32_t sources, int32_t keyboardType) :
841 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
842 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700843 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700844}
845
846KeyboardInputMapper::~KeyboardInputMapper() {
847}
848
Jeff Brownb51719b2010-07-29 18:18:33 -0700849void KeyboardInputMapper::initializeLocked() {
850 mLocked.metaState = AMETA_NONE;
851 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700852}
853
854uint32_t KeyboardInputMapper::getSources() {
855 return mSources;
856}
857
858void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
859 InputMapper::populateDeviceInfo(info);
860
861 info->setKeyboardType(mKeyboardType);
862}
863
Jeff Brown26c94ff2010-09-30 14:33:04 -0700864void KeyboardInputMapper::dump(String8& dump) {
865 { // acquire lock
866 AutoMutex _l(mLock);
867 dump.append(INDENT2 "Keyboard Input Mapper:\n");
868 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
Jeff Brown26c94ff2010-09-30 14:33:04 -0700869 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
870 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
871 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
872 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
873 } // release lock
874}
875
Jeff Browne57e8952010-07-23 21:28:06 -0700876void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700877 for (;;) {
878 int32_t keyCode, scanCode;
879 { // acquire lock
880 AutoMutex _l(mLock);
881
882 // Synthesize key up event on reset if keys are currently down.
883 if (mLocked.keyDowns.isEmpty()) {
884 initializeLocked();
885 break; // done
886 }
887
888 const KeyDown& keyDown = mLocked.keyDowns.top();
889 keyCode = keyDown.keyCode;
890 scanCode = keyDown.scanCode;
891 } // release lock
892
Jeff Browne57e8952010-07-23 21:28:06 -0700893 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700894 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700895 }
896
897 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700898 getContext()->updateGlobalMetaState();
899}
900
901void KeyboardInputMapper::process(const RawEvent* rawEvent) {
902 switch (rawEvent->type) {
903 case EV_KEY: {
904 int32_t scanCode = rawEvent->scanCode;
905 if (isKeyboardOrGamepadKey(scanCode)) {
906 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
907 rawEvent->flags);
908 }
909 break;
910 }
911 }
912}
913
914bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
915 return scanCode < BTN_MOUSE
916 || scanCode >= KEY_OK
917 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
918}
919
Jeff Brownb51719b2010-07-29 18:18:33 -0700920void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
921 int32_t scanCode, uint32_t policyFlags) {
922 int32_t newMetaState;
923 nsecs_t downTime;
924 bool metaStateChanged = false;
925
926 { // acquire lock
927 AutoMutex _l(mLock);
928
929 if (down) {
930 // Rotate key codes according to orientation if needed.
931 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
932 if (mAssociatedDisplayId >= 0) {
933 int32_t orientation;
934 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
935 return;
936 }
937
938 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700939 }
940
Jeff Brownb51719b2010-07-29 18:18:33 -0700941 // Add key down.
942 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
943 if (keyDownIndex >= 0) {
944 // key repeat, be sure to use same keycode as before in case of rotation
945 keyCode = mLocked.keyDowns.top().keyCode;
946 } else {
947 // key down
948 mLocked.keyDowns.push();
949 KeyDown& keyDown = mLocked.keyDowns.editTop();
950 keyDown.keyCode = keyCode;
951 keyDown.scanCode = scanCode;
952 }
953
954 mLocked.downTime = when;
955 } else {
956 // Remove key down.
957 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
958 if (keyDownIndex >= 0) {
959 // key up, be sure to use same keycode as before in case of rotation
960 keyCode = mLocked.keyDowns.top().keyCode;
961 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
962 } else {
963 // key was not actually down
964 LOGI("Dropping key up from device %s because the key was not down. "
965 "keyCode=%d, scanCode=%d",
966 getDeviceName().string(), keyCode, scanCode);
967 return;
968 }
Jeff Browne57e8952010-07-23 21:28:06 -0700969 }
970
Jeff Brownb51719b2010-07-29 18:18:33 -0700971 int32_t oldMetaState = mLocked.metaState;
972 newMetaState = updateMetaState(keyCode, down, oldMetaState);
973 if (oldMetaState != newMetaState) {
974 mLocked.metaState = newMetaState;
975 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700976 }
Jeff Brown8575a872010-06-30 16:10:35 -0700977
Jeff Brownb51719b2010-07-29 18:18:33 -0700978 downTime = mLocked.downTime;
979 } // release lock
980
981 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700982 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700983 }
984
Jeff Brownb51719b2010-07-29 18:18:33 -0700985 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
986}
Jeff Browne839a582010-04-22 18:58:52 -0700987
Jeff Brownb51719b2010-07-29 18:18:33 -0700988void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
989 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -0700990 int32_t policyActions = getPolicy()->interceptKey(when,
991 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700992
Jeff Browne57e8952010-07-23 21:28:06 -0700993 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Browne839a582010-04-22 18:58:52 -0700994 return; // event dropped
995 }
996
Jeff Brownb51719b2010-07-29 18:18:33 -0700997 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700998 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Browne57e8952010-07-23 21:28:06 -0700999 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brown956c0fb2010-10-01 14:55:30 -07001000 keyEventFlags |= AKEY_EVENT_FLAG_WOKE_HERE;
1001 }
1002 if (policyFlags & POLICY_FLAG_VIRTUAL) {
1003 keyEventFlags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
Jeff Browne839a582010-04-22 18:58:52 -07001004 }
1005
Jeff Browne57e8952010-07-23 21:28:06 -07001006 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brownb51719b2010-07-29 18:18:33 -07001007 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001008}
1009
Jeff Brownb51719b2010-07-29 18:18:33 -07001010ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1011 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -07001012 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001013 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07001014 return i;
1015 }
1016 }
1017 return -1;
Jeff Browne839a582010-04-22 18:58:52 -07001018}
1019
Jeff Browne57e8952010-07-23 21:28:06 -07001020int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1021 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1022}
Jeff Browne839a582010-04-22 18:58:52 -07001023
Jeff Browne57e8952010-07-23 21:28:06 -07001024int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1025 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1026}
Jeff Browne839a582010-04-22 18:58:52 -07001027
Jeff Browne57e8952010-07-23 21:28:06 -07001028bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1029 const int32_t* keyCodes, uint8_t* outFlags) {
1030 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1031}
1032
1033int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001034 { // acquire lock
1035 AutoMutex _l(mLock);
1036 return mLocked.metaState;
1037 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001038}
1039
1040
1041// --- TrackballInputMapper ---
1042
1043TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1044 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1045 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1046 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1047 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1048 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1049
Jeff Brownb51719b2010-07-29 18:18:33 -07001050 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001051}
1052
1053TrackballInputMapper::~TrackballInputMapper() {
1054}
1055
1056uint32_t TrackballInputMapper::getSources() {
1057 return AINPUT_SOURCE_TRACKBALL;
1058}
1059
1060void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1061 InputMapper::populateDeviceInfo(info);
1062
1063 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1064 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1065}
1066
Jeff Brown26c94ff2010-09-30 14:33:04 -07001067void TrackballInputMapper::dump(String8& dump) {
1068 { // acquire lock
1069 AutoMutex _l(mLock);
1070 dump.append(INDENT2 "Trackball Input Mapper:\n");
1071 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1072 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1073 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1074 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1075 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1076 } // release lock
1077}
1078
Jeff Brownb51719b2010-07-29 18:18:33 -07001079void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001080 mAccumulator.clear();
1081
Jeff Brownb51719b2010-07-29 18:18:33 -07001082 mLocked.down = false;
1083 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001084}
1085
1086void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001087 for (;;) {
1088 { // acquire lock
1089 AutoMutex _l(mLock);
1090
1091 if (! mLocked.down) {
1092 initializeLocked();
1093 break; // done
1094 }
1095 } // release lock
1096
1097 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001098 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001099 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001100 mAccumulator.btnMouse = false;
1101 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001102 }
1103
Jeff Browne57e8952010-07-23 21:28:06 -07001104 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001105}
Jeff Browne839a582010-04-22 18:58:52 -07001106
Jeff Browne57e8952010-07-23 21:28:06 -07001107void TrackballInputMapper::process(const RawEvent* rawEvent) {
1108 switch (rawEvent->type) {
1109 case EV_KEY:
1110 switch (rawEvent->scanCode) {
1111 case BTN_MOUSE:
1112 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1113 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001114 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1115 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001116 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001117 break;
Jeff Browne839a582010-04-22 18:58:52 -07001118 }
Jeff Browne57e8952010-07-23 21:28:06 -07001119 break;
Jeff Browne839a582010-04-22 18:58:52 -07001120
Jeff Browne57e8952010-07-23 21:28:06 -07001121 case EV_REL:
1122 switch (rawEvent->scanCode) {
1123 case REL_X:
1124 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1125 mAccumulator.relX = rawEvent->value;
1126 break;
1127 case REL_Y:
1128 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1129 mAccumulator.relY = rawEvent->value;
1130 break;
Jeff Browne839a582010-04-22 18:58:52 -07001131 }
Jeff Browne57e8952010-07-23 21:28:06 -07001132 break;
Jeff Browne839a582010-04-22 18:58:52 -07001133
Jeff Browne57e8952010-07-23 21:28:06 -07001134 case EV_SYN:
1135 switch (rawEvent->scanCode) {
1136 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001137 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001138 break;
Jeff Browne839a582010-04-22 18:58:52 -07001139 }
Jeff Browne57e8952010-07-23 21:28:06 -07001140 break;
Jeff Browne839a582010-04-22 18:58:52 -07001141 }
Jeff Browne839a582010-04-22 18:58:52 -07001142}
1143
Jeff Browne57e8952010-07-23 21:28:06 -07001144void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001145 uint32_t fields = mAccumulator.fields;
1146 if (fields == 0) {
1147 return; // no new state changes, so nothing to do
1148 }
1149
Jeff Brownb51719b2010-07-29 18:18:33 -07001150 int motionEventAction;
1151 PointerCoords pointerCoords;
1152 nsecs_t downTime;
1153 { // acquire lock
1154 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001155
Jeff Brownb51719b2010-07-29 18:18:33 -07001156 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1157
1158 if (downChanged) {
1159 if (mAccumulator.btnMouse) {
1160 mLocked.down = true;
1161 mLocked.downTime = when;
1162 } else {
1163 mLocked.down = false;
1164 }
Jeff Browne57e8952010-07-23 21:28:06 -07001165 }
Jeff Browne839a582010-04-22 18:58:52 -07001166
Jeff Brownb51719b2010-07-29 18:18:33 -07001167 downTime = mLocked.downTime;
1168 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1169 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001170
Jeff Brownb51719b2010-07-29 18:18:33 -07001171 if (downChanged) {
1172 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001173 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001174 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001175 }
Jeff Browne839a582010-04-22 18:58:52 -07001176
Jeff Brownb51719b2010-07-29 18:18:33 -07001177 pointerCoords.x = x;
1178 pointerCoords.y = y;
1179 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1180 pointerCoords.size = 0;
1181 pointerCoords.touchMajor = 0;
1182 pointerCoords.touchMinor = 0;
1183 pointerCoords.toolMajor = 0;
1184 pointerCoords.toolMinor = 0;
1185 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001186
Jeff Brownb51719b2010-07-29 18:18:33 -07001187 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1188 // Rotate motion based on display orientation if needed.
1189 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1190 int32_t orientation;
1191 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1192 return;
1193 }
1194
1195 float temp;
1196 switch (orientation) {
1197 case InputReaderPolicyInterface::ROTATION_90:
1198 temp = pointerCoords.x;
1199 pointerCoords.x = pointerCoords.y;
1200 pointerCoords.y = - temp;
1201 break;
1202
1203 case InputReaderPolicyInterface::ROTATION_180:
1204 pointerCoords.x = - pointerCoords.x;
1205 pointerCoords.y = - pointerCoords.y;
1206 break;
1207
1208 case InputReaderPolicyInterface::ROTATION_270:
1209 temp = pointerCoords.x;
1210 pointerCoords.x = - pointerCoords.y;
1211 pointerCoords.y = temp;
1212 break;
1213 }
1214 }
1215 } // release lock
1216
1217 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
Jeff Brownd64c8552010-08-17 20:38:35 -07001218
1219 mAccumulator.clear();
Jeff Brownb51719b2010-07-29 18:18:33 -07001220}
1221
1222void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1223 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001224 uint32_t policyFlags = 0;
1225 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1226
1227 if (! applyStandardPolicyActions(when, policyActions)) {
1228 return; // event dropped
1229 }
1230
Jeff Browne57e8952010-07-23 21:28:06 -07001231 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001232 int32_t pointerId = 0;
1233
Jeff Browne57e8952010-07-23 21:28:06 -07001234 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001235 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001236 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001237}
1238
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001239int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1240 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1241 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1242 } else {
1243 return AKEY_STATE_UNKNOWN;
1244 }
1245}
1246
Jeff Browne57e8952010-07-23 21:28:06 -07001247
1248// --- TouchInputMapper ---
1249
1250TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001251 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1252 mLocked.surfaceOrientation = -1;
1253 mLocked.surfaceWidth = -1;
1254 mLocked.surfaceHeight = -1;
1255
1256 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001257}
1258
1259TouchInputMapper::~TouchInputMapper() {
1260}
1261
1262uint32_t TouchInputMapper::getSources() {
1263 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1264}
1265
1266void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1267 InputMapper::populateDeviceInfo(info);
1268
Jeff Brownb51719b2010-07-29 18:18:33 -07001269 { // acquire lock
1270 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001271
Jeff Brownb51719b2010-07-29 18:18:33 -07001272 // Ensure surface information is up to date so that orientation changes are
1273 // noticed immediately.
1274 configureSurfaceLocked();
1275
1276 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1277 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001278
1279 if (mLocked.orientedRanges.havePressure) {
1280 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1281 mLocked.orientedRanges.pressure);
1282 }
1283
1284 if (mLocked.orientedRanges.haveSize) {
1285 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1286 mLocked.orientedRanges.size);
1287 }
1288
1289 if (mLocked.orientedRanges.haveTouchArea) {
1290 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1291 mLocked.orientedRanges.touchMajor);
1292 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1293 mLocked.orientedRanges.touchMinor);
1294 }
1295
1296 if (mLocked.orientedRanges.haveToolArea) {
1297 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1298 mLocked.orientedRanges.toolMajor);
1299 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1300 mLocked.orientedRanges.toolMinor);
1301 }
1302
1303 if (mLocked.orientedRanges.haveOrientation) {
1304 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1305 mLocked.orientedRanges.orientation);
1306 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001307 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001308}
1309
Jeff Brown26c94ff2010-09-30 14:33:04 -07001310void TouchInputMapper::dump(String8& dump) {
1311 { // acquire lock
1312 AutoMutex _l(mLock);
1313 dump.append(INDENT2 "Touch Input Mapper:\n");
1314 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1315 dumpParameters(dump);
1316 dumpVirtualKeysLocked(dump);
1317 dumpRawAxes(dump);
1318 dumpCalibration(dump);
1319 dumpSurfaceLocked(dump);
1320 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mLocked.xPrecision);
1321 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mLocked.yPrecision);
1322 } // release lock
1323}
1324
Jeff Brownb51719b2010-07-29 18:18:33 -07001325void TouchInputMapper::initializeLocked() {
1326 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001327 mLastTouch.clear();
1328 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001329
1330 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1331 mAveragingTouchFilter.historyStart[i] = 0;
1332 mAveragingTouchFilter.historyEnd[i] = 0;
1333 }
1334
1335 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001336
1337 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001338
1339 mLocked.orientedRanges.havePressure = false;
1340 mLocked.orientedRanges.haveSize = false;
1341 mLocked.orientedRanges.haveTouchArea = false;
1342 mLocked.orientedRanges.haveToolArea = false;
1343 mLocked.orientedRanges.haveOrientation = false;
1344}
1345
Jeff Browne57e8952010-07-23 21:28:06 -07001346void TouchInputMapper::configure() {
1347 InputMapper::configure();
1348
1349 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001350 configureParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001351
1352 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001353 configureRawAxes();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001354
1355 // Prepare input device calibration.
1356 parseCalibration();
1357 resolveCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001358
Jeff Brownb51719b2010-07-29 18:18:33 -07001359 { // acquire lock
1360 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001361
Jeff Brown38a7fab2010-08-30 03:02:23 -07001362 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001363 configureSurfaceLocked();
1364 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001365}
1366
Jeff Brown38a7fab2010-08-30 03:02:23 -07001367void TouchInputMapper::configureParameters() {
1368 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1369 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1370 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1371}
1372
Jeff Brown26c94ff2010-09-30 14:33:04 -07001373void TouchInputMapper::dumpParameters(String8& dump) {
1374 dump.appendFormat(INDENT3 "UseBadTouchFilter: %s\n",
1375 toString(mParameters.useBadTouchFilter));
1376 dump.appendFormat(INDENT3 "UseAveragingTouchFilter: %s\n",
1377 toString(mParameters.useAveragingTouchFilter));
1378 dump.appendFormat(INDENT3 "UseJumpyTouchFilter: %s\n",
1379 toString(mParameters.useJumpyTouchFilter));
Jeff Browna665ca82010-09-08 11:49:43 -07001380}
1381
Jeff Brown38a7fab2010-08-30 03:02:23 -07001382void TouchInputMapper::configureRawAxes() {
1383 mRawAxes.x.clear();
1384 mRawAxes.y.clear();
1385 mRawAxes.pressure.clear();
1386 mRawAxes.touchMajor.clear();
1387 mRawAxes.touchMinor.clear();
1388 mRawAxes.toolMajor.clear();
1389 mRawAxes.toolMinor.clear();
1390 mRawAxes.orientation.clear();
1391}
1392
Jeff Brown26c94ff2010-09-30 14:33:04 -07001393static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Browna665ca82010-09-08 11:49:43 -07001394 if (axis.valid) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001395 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Browna665ca82010-09-08 11:49:43 -07001396 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1397 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001398 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Browna665ca82010-09-08 11:49:43 -07001399 }
1400}
1401
Jeff Brown26c94ff2010-09-30 14:33:04 -07001402void TouchInputMapper::dumpRawAxes(String8& dump) {
1403 dump.append(INDENT3 "Raw Axes:\n");
1404 dumpAxisInfo(dump, mRawAxes.x, "X");
1405 dumpAxisInfo(dump, mRawAxes.y, "Y");
1406 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1407 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1408 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1409 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1410 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1411 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001412}
1413
Jeff Brownb51719b2010-07-29 18:18:33 -07001414bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001415 // Update orientation and dimensions if needed.
1416 int32_t orientation;
1417 int32_t width, height;
1418 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001419 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001420 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1421 return false;
1422 }
1423 } else {
1424 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001425 width = mRawAxes.x.getRange();
1426 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001427 }
1428
Jeff Brownb51719b2010-07-29 18:18:33 -07001429 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001430 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001431 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001432 }
1433
Jeff Brownb51719b2010-07-29 18:18:33 -07001434 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001435 if (sizeChanged) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001436 LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
1437 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001438
Jeff Brownb51719b2010-07-29 18:18:33 -07001439 mLocked.surfaceWidth = width;
1440 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001441
Jeff Brown38a7fab2010-08-30 03:02:23 -07001442 // Configure X and Y factors.
1443 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1444 mLocked.xOrigin = mRawAxes.x.minValue;
1445 mLocked.yOrigin = mRawAxes.y.minValue;
1446 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1447 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001448 mLocked.xPrecision = 1.0f / mLocked.xScale;
1449 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001450
Jeff Brownb51719b2010-07-29 18:18:33 -07001451 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001452 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001453 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001454 mLocked.xOrigin = 0;
1455 mLocked.yOrigin = 0;
1456 mLocked.xScale = 1.0f;
1457 mLocked.yScale = 1.0f;
1458 mLocked.xPrecision = 1.0f;
1459 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001460 }
1461
Jeff Brown38a7fab2010-08-30 03:02:23 -07001462 // Scale factor for terms that are not oriented in a particular axis.
1463 // If the pixels are square then xScale == yScale otherwise we fake it
1464 // by choosing an average.
1465 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001466
Jeff Brown38a7fab2010-08-30 03:02:23 -07001467 // Size of diagonal axis.
1468 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001469
Jeff Brown38a7fab2010-08-30 03:02:23 -07001470 // TouchMajor and TouchMinor factors.
1471 if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) {
1472 mLocked.orientedRanges.haveTouchArea = true;
1473 mLocked.orientedRanges.touchMajor.min = 0;
1474 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1475 mLocked.orientedRanges.touchMajor.flat = 0;
1476 mLocked.orientedRanges.touchMajor.fuzz = 0;
1477 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1478 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001479
Jeff Brown38a7fab2010-08-30 03:02:23 -07001480 // ToolMajor and ToolMinor factors.
1481 if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1482 mLocked.toolAreaLinearScale = 0;
1483 mLocked.toolAreaLinearBias = 0;
1484 if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) {
1485 if (mCalibration.haveToolAreaLinearScale) {
1486 mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale;
1487 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1488 mLocked.toolAreaLinearScale = float(min(width, height))
1489 / mRawAxes.toolMajor.maxValue;
1490 }
1491
1492 if (mCalibration.haveToolAreaLinearBias) {
1493 mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias;
1494 }
1495 }
1496
1497 mLocked.orientedRanges.haveToolArea = true;
1498 mLocked.orientedRanges.toolMajor.min = 0;
1499 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1500 mLocked.orientedRanges.toolMajor.flat = 0;
1501 mLocked.orientedRanges.toolMajor.fuzz = 0;
1502 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1503 }
1504
1505 // Pressure factors.
1506 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1507 RawAbsoluteAxisInfo rawPressureAxis;
1508 switch (mCalibration.pressureSource) {
1509 case Calibration::PRESSURE_SOURCE_PRESSURE:
1510 rawPressureAxis = mRawAxes.pressure;
1511 break;
1512 case Calibration::PRESSURE_SOURCE_TOUCH:
1513 rawPressureAxis = mRawAxes.touchMajor;
1514 break;
1515 default:
1516 rawPressureAxis.clear();
1517 }
1518
1519 mLocked.pressureScale = 0;
1520 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1521 || mCalibration.pressureCalibration
1522 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1523 if (mCalibration.havePressureScale) {
1524 mLocked.pressureScale = mCalibration.pressureScale;
1525 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1526 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1527 }
1528 }
1529
1530 mLocked.orientedRanges.havePressure = true;
1531 mLocked.orientedRanges.pressure.min = 0;
1532 mLocked.orientedRanges.pressure.max = 1.0;
1533 mLocked.orientedRanges.pressure.flat = 0;
1534 mLocked.orientedRanges.pressure.fuzz = 0;
1535 }
1536
1537 // Size factors.
1538 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1539 mLocked.sizeScale = 0;
1540 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1541 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1542 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1543 }
1544 }
1545
1546 mLocked.orientedRanges.haveSize = true;
1547 mLocked.orientedRanges.size.min = 0;
1548 mLocked.orientedRanges.size.max = 1.0;
1549 mLocked.orientedRanges.size.flat = 0;
1550 mLocked.orientedRanges.size.fuzz = 0;
1551 }
1552
1553 // Orientation
1554 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1555 mLocked.orientationScale = 0;
1556 if (mCalibration.orientationCalibration
1557 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1558 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1559 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1560 }
1561 }
1562
1563 mLocked.orientedRanges.orientation.min = - M_PI_2;
1564 mLocked.orientedRanges.orientation.max = M_PI_2;
1565 mLocked.orientedRanges.orientation.flat = 0;
1566 mLocked.orientedRanges.orientation.fuzz = 0;
1567 }
Jeff Browne57e8952010-07-23 21:28:06 -07001568 }
1569
1570 if (orientationChanged || sizeChanged) {
1571 // Compute oriented surface dimensions, precision, and scales.
1572 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001573 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001574 case InputReaderPolicyInterface::ROTATION_90:
1575 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001576 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1577 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1578 mLocked.orientedXPrecision = mLocked.yPrecision;
1579 mLocked.orientedYPrecision = mLocked.xPrecision;
1580 orientedXScale = mLocked.yScale;
1581 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001582 break;
1583 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001584 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1585 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1586 mLocked.orientedXPrecision = mLocked.xPrecision;
1587 mLocked.orientedYPrecision = mLocked.yPrecision;
1588 orientedXScale = mLocked.xScale;
1589 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001590 break;
1591 }
1592
1593 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001594 mLocked.orientedRanges.x.min = 0;
1595 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1596 mLocked.orientedRanges.x.flat = 0;
1597 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001598
Jeff Brownb51719b2010-07-29 18:18:33 -07001599 mLocked.orientedRanges.y.min = 0;
1600 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1601 mLocked.orientedRanges.y.flat = 0;
1602 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001603 }
1604
1605 return true;
1606}
1607
Jeff Brown26c94ff2010-09-30 14:33:04 -07001608void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1609 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1610 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1611 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Browna665ca82010-09-08 11:49:43 -07001612}
1613
Jeff Brownb51719b2010-07-29 18:18:33 -07001614void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001615 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001616
Jeff Brownb51719b2010-07-29 18:18:33 -07001617 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001618 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001619 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1620
Jeff Brownb51719b2010-07-29 18:18:33 -07001621 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001622
Jeff Brownb51719b2010-07-29 18:18:33 -07001623 if (virtualKeyDefinitions.size() == 0) {
1624 return;
1625 }
Jeff Browne57e8952010-07-23 21:28:06 -07001626
Jeff Brownb51719b2010-07-29 18:18:33 -07001627 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1628
Jeff Brown38a7fab2010-08-30 03:02:23 -07001629 int32_t touchScreenLeft = mRawAxes.x.minValue;
1630 int32_t touchScreenTop = mRawAxes.y.minValue;
1631 int32_t touchScreenWidth = mRawAxes.x.getRange();
1632 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001633
1634 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001635 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001636 virtualKeyDefinitions[i];
1637
1638 mLocked.virtualKeys.add();
1639 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1640
1641 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1642 int32_t keyCode;
1643 uint32_t flags;
1644 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1645 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001646 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1647 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001648 mLocked.virtualKeys.pop(); // drop the key
1649 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001650 }
1651
Jeff Brownb51719b2010-07-29 18:18:33 -07001652 virtualKey.keyCode = keyCode;
1653 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001654
Jeff Brownb51719b2010-07-29 18:18:33 -07001655 // convert the key definition's display coordinates into touch coordinates for a hit box
1656 int32_t halfWidth = virtualKeyDefinition.width / 2;
1657 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001658
Jeff Brownb51719b2010-07-29 18:18:33 -07001659 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1660 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1661 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1662 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1663 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1664 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1665 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1666 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001667
Jeff Brown26c94ff2010-09-30 14:33:04 -07001668 }
1669}
1670
1671void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1672 if (!mLocked.virtualKeys.isEmpty()) {
1673 dump.append(INDENT3 "Virtual Keys:\n");
1674
1675 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1676 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1677 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1678 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1679 i, virtualKey.scanCode, virtualKey.keyCode,
1680 virtualKey.hitLeft, virtualKey.hitRight,
1681 virtualKey.hitTop, virtualKey.hitBottom);
1682 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001683 }
Jeff Browne57e8952010-07-23 21:28:06 -07001684}
1685
Jeff Brown38a7fab2010-08-30 03:02:23 -07001686void TouchInputMapper::parseCalibration() {
1687 const InputDeviceCalibration& in = getDevice()->getCalibration();
1688 Calibration& out = mCalibration;
1689
1690 // Touch Area
1691 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT;
1692 String8 touchAreaCalibrationString;
1693 if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) {
1694 if (touchAreaCalibrationString == "none") {
1695 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1696 } else if (touchAreaCalibrationString == "geometric") {
1697 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC;
1698 } else if (touchAreaCalibrationString == "pressure") {
1699 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1700 } else if (touchAreaCalibrationString != "default") {
1701 LOGW("Invalid value for touch.touchArea.calibration: '%s'",
1702 touchAreaCalibrationString.string());
1703 }
1704 }
1705
1706 // Tool Area
1707 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT;
1708 String8 toolAreaCalibrationString;
1709 if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) {
1710 if (toolAreaCalibrationString == "none") {
1711 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1712 } else if (toolAreaCalibrationString == "geometric") {
1713 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC;
1714 } else if (toolAreaCalibrationString == "linear") {
1715 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1716 } else if (toolAreaCalibrationString != "default") {
1717 LOGW("Invalid value for tool.toolArea.calibration: '%s'",
1718 toolAreaCalibrationString.string());
1719 }
1720 }
1721
1722 out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"),
1723 out.toolAreaLinearScale);
1724 out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"),
1725 out.toolAreaLinearBias);
1726 out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"),
1727 out.toolAreaIsSummed);
1728
1729 // Pressure
1730 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1731 String8 pressureCalibrationString;
1732 if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) {
1733 if (pressureCalibrationString == "none") {
1734 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1735 } else if (pressureCalibrationString == "physical") {
1736 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1737 } else if (pressureCalibrationString == "amplitude") {
1738 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1739 } else if (pressureCalibrationString != "default") {
1740 LOGW("Invalid value for tool.pressure.calibration: '%s'",
1741 pressureCalibrationString.string());
1742 }
1743 }
1744
1745 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1746 String8 pressureSourceString;
1747 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1748 if (pressureSourceString == "pressure") {
1749 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1750 } else if (pressureSourceString == "touch") {
1751 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1752 } else if (pressureSourceString != "default") {
1753 LOGW("Invalid value for touch.pressure.source: '%s'",
1754 pressureSourceString.string());
1755 }
1756 }
1757
1758 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1759 out.pressureScale);
1760
1761 // Size
1762 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1763 String8 sizeCalibrationString;
1764 if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) {
1765 if (sizeCalibrationString == "none") {
1766 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1767 } else if (sizeCalibrationString == "normalized") {
1768 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1769 } else if (sizeCalibrationString != "default") {
1770 LOGW("Invalid value for tool.size.calibration: '%s'",
1771 sizeCalibrationString.string());
1772 }
1773 }
1774
1775 // Orientation
1776 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1777 String8 orientationCalibrationString;
1778 if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) {
1779 if (orientationCalibrationString == "none") {
1780 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1781 } else if (orientationCalibrationString == "interpolated") {
1782 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1783 } else if (orientationCalibrationString != "default") {
1784 LOGW("Invalid value for tool.orientation.calibration: '%s'",
1785 orientationCalibrationString.string());
1786 }
1787 }
1788}
1789
1790void TouchInputMapper::resolveCalibration() {
1791 // Pressure
1792 switch (mCalibration.pressureSource) {
1793 case Calibration::PRESSURE_SOURCE_DEFAULT:
1794 if (mRawAxes.pressure.valid) {
1795 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1796 } else if (mRawAxes.touchMajor.valid) {
1797 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1798 }
1799 break;
1800
1801 case Calibration::PRESSURE_SOURCE_PRESSURE:
1802 if (! mRawAxes.pressure.valid) {
1803 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1804 "the pressure axis is not available.");
1805 }
1806 break;
1807
1808 case Calibration::PRESSURE_SOURCE_TOUCH:
1809 if (! mRawAxes.touchMajor.valid) {
1810 LOGW("Calibration property touch.pressure.source is 'touch' but "
1811 "the touchMajor axis is not available.");
1812 }
1813 break;
1814
1815 default:
1816 break;
1817 }
1818
1819 switch (mCalibration.pressureCalibration) {
1820 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1821 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1822 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1823 } else {
1824 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1825 }
1826 break;
1827
1828 default:
1829 break;
1830 }
1831
1832 // Tool Area
1833 switch (mCalibration.toolAreaCalibration) {
1834 case Calibration::TOOL_AREA_CALIBRATION_DEFAULT:
1835 if (mRawAxes.toolMajor.valid) {
1836 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1837 } else {
1838 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1839 }
1840 break;
1841
1842 default:
1843 break;
1844 }
1845
1846 // Touch Area
1847 switch (mCalibration.touchAreaCalibration) {
1848 case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT:
1849 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
1850 && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1851 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1852 } else {
1853 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1854 }
1855 break;
1856
1857 default:
1858 break;
1859 }
1860
1861 // Size
1862 switch (mCalibration.sizeCalibration) {
1863 case Calibration::SIZE_CALIBRATION_DEFAULT:
1864 if (mRawAxes.toolMajor.valid) {
1865 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1866 } else {
1867 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1868 }
1869 break;
1870
1871 default:
1872 break;
1873 }
1874
1875 // Orientation
1876 switch (mCalibration.orientationCalibration) {
1877 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1878 if (mRawAxes.orientation.valid) {
1879 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1880 } else {
1881 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1882 }
1883 break;
1884
1885 default:
1886 break;
1887 }
1888}
1889
Jeff Brown26c94ff2010-09-30 14:33:04 -07001890void TouchInputMapper::dumpCalibration(String8& dump) {
1891 dump.append(INDENT3 "Calibration:\n");
Jeff Browna665ca82010-09-08 11:49:43 -07001892
Jeff Brown38a7fab2010-08-30 03:02:23 -07001893 // Touch Area
1894 switch (mCalibration.touchAreaCalibration) {
1895 case Calibration::TOUCH_AREA_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001896 dump.append(INDENT4 "touch.touchArea.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001897 break;
1898 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001899 dump.append(INDENT4 "touch.touchArea.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001900 break;
1901 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001902 dump.append(INDENT4 "touch.touchArea.calibration: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001903 break;
1904 default:
1905 assert(false);
1906 }
1907
1908 // Tool Area
1909 switch (mCalibration.toolAreaCalibration) {
1910 case Calibration::TOOL_AREA_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001911 dump.append(INDENT4 "touch.toolArea.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001912 break;
1913 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001914 dump.append(INDENT4 "touch.toolArea.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001915 break;
1916 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001917 dump.append(INDENT4 "touch.toolArea.calibration: linear\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001918 break;
1919 default:
1920 assert(false);
1921 }
1922
1923 if (mCalibration.haveToolAreaLinearScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001924 dump.appendFormat(INDENT4 "touch.toolArea.linearScale: %0.3f\n",
1925 mCalibration.toolAreaLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001926 }
1927
1928 if (mCalibration.haveToolAreaLinearBias) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001929 dump.appendFormat(INDENT4 "touch.toolArea.linearBias: %0.3f\n",
1930 mCalibration.toolAreaLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001931 }
1932
1933 if (mCalibration.haveToolAreaIsSummed) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001934 dump.appendFormat(INDENT4 "touch.toolArea.isSummed: %d\n",
1935 mCalibration.toolAreaIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001936 }
1937
1938 // Pressure
1939 switch (mCalibration.pressureCalibration) {
1940 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001941 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001942 break;
1943 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001944 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001945 break;
1946 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001947 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001948 break;
1949 default:
1950 assert(false);
1951 }
1952
1953 switch (mCalibration.pressureSource) {
1954 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001955 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001956 break;
1957 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001958 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001959 break;
1960 case Calibration::PRESSURE_SOURCE_DEFAULT:
1961 break;
1962 default:
1963 assert(false);
1964 }
1965
1966 if (mCalibration.havePressureScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001967 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
1968 mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001969 }
1970
1971 // Size
1972 switch (mCalibration.sizeCalibration) {
1973 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001974 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001975 break;
1976 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001977 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001978 break;
1979 default:
1980 assert(false);
1981 }
1982
1983 // Orientation
1984 switch (mCalibration.orientationCalibration) {
1985 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001986 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001987 break;
1988 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001989 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001990 break;
1991 default:
1992 assert(false);
1993 }
1994}
1995
Jeff Browne57e8952010-07-23 21:28:06 -07001996void TouchInputMapper::reset() {
1997 // Synthesize touch up event if touch is currently down.
1998 // This will also take care of finishing virtual key processing if needed.
1999 if (mLastTouch.pointerCount != 0) {
2000 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2001 mCurrentTouch.clear();
2002 syncTouch(when, true);
2003 }
2004
Jeff Brownb51719b2010-07-29 18:18:33 -07002005 { // acquire lock
2006 AutoMutex _l(mLock);
2007 initializeLocked();
2008 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002009
Jeff Brownb51719b2010-07-29 18:18:33 -07002010 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07002011}
2012
2013void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002014 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07002015
2016 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07002017 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
2018
2019 if (! applyStandardPolicyActions(when, policyActions)) {
2020 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07002021 return; // event dropped
2022 }
2023
Jeff Brownb51719b2010-07-29 18:18:33 -07002024 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07002025
Jeff Browne57e8952010-07-23 21:28:06 -07002026 if (mParameters.useBadTouchFilter) {
2027 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002028 havePointerIds = false;
2029 }
2030 }
2031
Jeff Browne57e8952010-07-23 21:28:06 -07002032 if (mParameters.useJumpyTouchFilter) {
2033 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002034 havePointerIds = false;
2035 }
2036 }
2037
2038 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002039 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002040 }
2041
Jeff Browne57e8952010-07-23 21:28:06 -07002042 TouchData temp;
2043 TouchData* savedTouch;
2044 if (mParameters.useAveragingTouchFilter) {
2045 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002046 savedTouch = & temp;
2047
Jeff Browne57e8952010-07-23 21:28:06 -07002048 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002049 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002050 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002051 }
2052
Jeff Brownb51719b2010-07-29 18:18:33 -07002053 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002054
Jeff Browne57e8952010-07-23 21:28:06 -07002055 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2056 if (touchResult == DISPATCH_TOUCH) {
2057 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002058 }
2059
Jeff Brownb51719b2010-07-29 18:18:33 -07002060 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002061
Jeff Browne57e8952010-07-23 21:28:06 -07002062 if (touchResult == DROP_STROKE) {
2063 mLastTouch.clear();
2064 } else {
2065 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002066 }
Jeff Browne839a582010-04-22 18:58:52 -07002067}
2068
Jeff Browne57e8952010-07-23 21:28:06 -07002069TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2070 nsecs_t when, uint32_t policyFlags) {
2071 int32_t keyEventAction, keyEventFlags;
2072 int32_t keyCode, scanCode, downTime;
2073 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002074
Jeff Brownb51719b2010-07-29 18:18:33 -07002075 { // acquire lock
2076 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002077
Jeff Brownb51719b2010-07-29 18:18:33 -07002078 // Update surface size and orientation, including virtual key positions.
2079 if (! configureSurfaceLocked()) {
2080 return DROP_STROKE;
2081 }
2082
2083 // Check for virtual key press.
2084 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002085 if (mCurrentTouch.pointerCount == 0) {
2086 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002087 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002088#if DEBUG_VIRTUAL_KEYS
2089 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
2090 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2091#endif
2092 keyEventAction = AKEY_EVENT_ACTION_UP;
2093 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2094 touchResult = SKIP_TOUCH;
2095 goto DispatchVirtualKey;
2096 }
2097
2098 if (mCurrentTouch.pointerCount == 1) {
2099 int32_t x = mCurrentTouch.pointers[0].x;
2100 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002101 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2102 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002103 // Pointer is still within the space of the virtual key.
2104 return SKIP_TOUCH;
2105 }
2106 }
2107
2108 // Pointer left virtual key area or another pointer also went down.
2109 // Send key cancellation and drop the stroke so subsequent motions will be
2110 // considered fresh downs. This is useful when the user swipes away from the
2111 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002112 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002113#if DEBUG_VIRTUAL_KEYS
2114 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
2115 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2116#endif
2117 keyEventAction = AKEY_EVENT_ACTION_UP;
2118 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2119 | AKEY_EVENT_FLAG_CANCELED;
2120 touchResult = DROP_STROKE;
2121 goto DispatchVirtualKey;
2122 } else {
2123 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2124 // Pointer just went down. Handle off-screen touches, if needed.
2125 int32_t x = mCurrentTouch.pointers[0].x;
2126 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002127 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002128 // If exactly one pointer went down, check for virtual key hit.
2129 // Otherwise we will drop the entire stroke.
2130 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002131 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002132 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002133 mLocked.currentVirtualKey.down = true;
2134 mLocked.currentVirtualKey.downTime = when;
2135 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2136 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002137#if DEBUG_VIRTUAL_KEYS
2138 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2139 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2140#endif
2141 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2142 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2143 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2144 touchResult = SKIP_TOUCH;
2145 goto DispatchVirtualKey;
2146 }
2147 }
2148 return DROP_STROKE;
2149 }
2150 }
2151 return DISPATCH_TOUCH;
2152 }
2153
2154 DispatchVirtualKey:
2155 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002156 keyCode = mLocked.currentVirtualKey.keyCode;
2157 scanCode = mLocked.currentVirtualKey.scanCode;
2158 downTime = mLocked.currentVirtualKey.downTime;
2159 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002160
2161 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002162 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
2163 keyCode, scanCode, downTime);
2164 return touchResult;
2165}
2166
2167void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
2168 int32_t keyEventAction, int32_t keyEventFlags,
2169 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07002170 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07002171
Jeff Brown956c0fb2010-10-01 14:55:30 -07002172 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Browne57e8952010-07-23 21:28:06 -07002173 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07002174 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07002175
Jeff Browne57e8952010-07-23 21:28:06 -07002176 if (applyStandardPolicyActions(when, policyActions)) {
2177 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07002178 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2179 }
Jeff Browne839a582010-04-22 18:58:52 -07002180}
2181
Jeff Browne57e8952010-07-23 21:28:06 -07002182void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2183 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2184 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002185 if (currentPointerCount == 0 && lastPointerCount == 0) {
2186 return; // nothing to do!
2187 }
2188
Jeff Browne57e8952010-07-23 21:28:06 -07002189 BitSet32 currentIdBits = mCurrentTouch.idBits;
2190 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002191
2192 if (currentIdBits == lastIdBits) {
2193 // No pointer id changes so this is a move event.
2194 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002195 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002196 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002197 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002198 } else {
2199 // There may be pointers going up and pointers going down at the same time when pointer
2200 // ids are reported by the device driver.
2201 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2202 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2203 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002204 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002205
2206 while (! upIdBits.isEmpty()) {
2207 uint32_t upId = upIdBits.firstMarkedBit();
2208 upIdBits.clearBit(upId);
2209 BitSet32 oldActiveIdBits = activeIdBits;
2210 activeIdBits.clearBit(upId);
2211
2212 int32_t motionEventAction;
2213 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002214 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002215 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002216 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002217 }
2218
Jeff Browne57e8952010-07-23 21:28:06 -07002219 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002220 oldActiveIdBits, upId, pointerCount, motionEventAction);
2221 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002222 }
2223
2224 while (! downIdBits.isEmpty()) {
2225 uint32_t downId = downIdBits.firstMarkedBit();
2226 downIdBits.clearBit(downId);
2227 BitSet32 oldActiveIdBits = activeIdBits;
2228 activeIdBits.markBit(downId);
2229
2230 int32_t motionEventAction;
2231 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002232 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002233 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002234 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002235 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002236 }
2237
Jeff Brown38a7fab2010-08-30 03:02:23 -07002238 pointerCount += 1;
Jeff Browne57e8952010-07-23 21:28:06 -07002239 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002240 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002241 }
2242 }
2243}
2244
Jeff Browne57e8952010-07-23 21:28:06 -07002245void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002246 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002247 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002248 int32_t pointerIds[MAX_POINTERS];
2249 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002250 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002251 float xPrecision, yPrecision;
2252
2253 { // acquire lock
2254 AutoMutex _l(mLock);
2255
2256 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2257 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002258 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002259 uint32_t id = idBits.firstMarkedBit();
2260 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002261 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002262
Jeff Brown38a7fab2010-08-30 03:02:23 -07002263 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002264
Jeff Brown38a7fab2010-08-30 03:02:23 -07002265 // X and Y
2266 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2267 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002268
Jeff Brown38a7fab2010-08-30 03:02:23 -07002269 // ToolMajor and ToolMinor
2270 float toolMajor, toolMinor;
2271 switch (mCalibration.toolAreaCalibration) {
2272 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
2273 toolMajor = in.toolMajor * mLocked.geometricScale;
2274 if (mRawAxes.toolMinor.valid) {
2275 toolMinor = in.toolMinor * mLocked.geometricScale;
2276 } else {
2277 toolMinor = toolMajor;
2278 }
2279 break;
2280 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
2281 toolMajor = in.toolMajor != 0
2282 ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias
2283 : 0;
2284 if (mRawAxes.toolMinor.valid) {
2285 toolMinor = in.toolMinor != 0
2286 ? in.toolMinor * mLocked.toolAreaLinearScale
2287 + mLocked.toolAreaLinearBias
2288 : 0;
2289 } else {
2290 toolMinor = toolMajor;
2291 }
2292 break;
2293 default:
2294 toolMajor = 0;
2295 toolMinor = 0;
2296 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002297 }
2298
Jeff Brown38a7fab2010-08-30 03:02:23 -07002299 if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) {
2300 toolMajor /= pointerCount;
2301 toolMinor /= pointerCount;
2302 }
2303
2304 // Pressure
2305 float rawPressure;
2306 switch (mCalibration.pressureSource) {
2307 case Calibration::PRESSURE_SOURCE_PRESSURE:
2308 rawPressure = in.pressure;
2309 break;
2310 case Calibration::PRESSURE_SOURCE_TOUCH:
2311 rawPressure = in.touchMajor;
2312 break;
2313 default:
2314 rawPressure = 0;
2315 }
2316
2317 float pressure;
2318 switch (mCalibration.pressureCalibration) {
2319 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2320 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2321 pressure = rawPressure * mLocked.pressureScale;
2322 break;
2323 default:
2324 pressure = 1;
2325 break;
2326 }
2327
2328 // TouchMajor and TouchMinor
2329 float touchMajor, touchMinor;
2330 switch (mCalibration.touchAreaCalibration) {
2331 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
2332 touchMajor = in.touchMajor * mLocked.geometricScale;
2333 if (mRawAxes.touchMinor.valid) {
2334 touchMinor = in.touchMinor * mLocked.geometricScale;
2335 } else {
2336 touchMinor = touchMajor;
2337 }
2338 break;
2339 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
2340 touchMajor = toolMajor * pressure;
2341 touchMinor = toolMinor * pressure;
2342 break;
2343 default:
2344 touchMajor = 0;
2345 touchMinor = 0;
2346 break;
2347 }
2348
2349 if (touchMajor > toolMajor) {
2350 touchMajor = toolMajor;
2351 }
2352 if (touchMinor > toolMinor) {
2353 touchMinor = toolMinor;
2354 }
2355
2356 // Size
2357 float size;
2358 switch (mCalibration.sizeCalibration) {
2359 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2360 float rawSize = mRawAxes.toolMinor.valid
2361 ? avg(in.toolMajor, in.toolMinor)
2362 : in.toolMajor;
2363 size = rawSize * mLocked.sizeScale;
2364 break;
2365 }
2366 default:
2367 size = 0;
2368 break;
2369 }
2370
2371 // Orientation
2372 float orientation;
2373 switch (mCalibration.orientationCalibration) {
2374 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2375 orientation = in.orientation * mLocked.orientationScale;
2376 break;
2377 default:
2378 orientation = 0;
2379 }
2380
2381 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002382 switch (mLocked.surfaceOrientation) {
2383 case InputReaderPolicyInterface::ROTATION_90: {
2384 float xTemp = x;
2385 x = y;
2386 y = mLocked.surfaceWidth - xTemp;
2387 orientation -= M_PI_2;
2388 if (orientation < - M_PI_2) {
2389 orientation += M_PI;
2390 }
2391 break;
2392 }
2393 case InputReaderPolicyInterface::ROTATION_180: {
2394 x = mLocked.surfaceWidth - x;
2395 y = mLocked.surfaceHeight - y;
2396 orientation = - orientation;
2397 break;
2398 }
2399 case InputReaderPolicyInterface::ROTATION_270: {
2400 float xTemp = x;
2401 x = mLocked.surfaceHeight - y;
2402 y = xTemp;
2403 orientation += M_PI_2;
2404 if (orientation > M_PI_2) {
2405 orientation -= M_PI;
2406 }
2407 break;
2408 }
2409 }
2410
Jeff Brown38a7fab2010-08-30 03:02:23 -07002411 // Write output coords.
2412 PointerCoords& out = pointerCoords[outIndex];
2413 out.x = x;
2414 out.y = y;
2415 out.pressure = pressure;
2416 out.size = size;
2417 out.touchMajor = touchMajor;
2418 out.touchMinor = touchMinor;
2419 out.toolMajor = toolMajor;
2420 out.toolMinor = toolMinor;
2421 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002422
Jeff Brown38a7fab2010-08-30 03:02:23 -07002423 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002424
2425 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002426 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002427 }
Jeff Browne839a582010-04-22 18:58:52 -07002428 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002429
2430 // Check edge flags by looking only at the first pointer since the flags are
2431 // global to the event.
2432 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2433 if (pointerCoords[0].x <= 0) {
2434 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2435 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2436 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2437 }
2438 if (pointerCoords[0].y <= 0) {
2439 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2440 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2441 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2442 }
Jeff Browne839a582010-04-22 18:58:52 -07002443 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002444
2445 xPrecision = mLocked.orientedXPrecision;
2446 yPrecision = mLocked.orientedYPrecision;
2447 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002448
Jeff Browne57e8952010-07-23 21:28:06 -07002449 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002450 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002451 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002452 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002453}
2454
Jeff Brownb51719b2010-07-29 18:18:33 -07002455bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002456 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2457 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2458 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002459 }
Jeff Browne57e8952010-07-23 21:28:06 -07002460 return true;
2461}
2462
Jeff Brownb51719b2010-07-29 18:18:33 -07002463const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2464 int32_t x, int32_t y) {
2465 size_t numVirtualKeys = mLocked.virtualKeys.size();
2466 for (size_t i = 0; i < numVirtualKeys; i++) {
2467 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002468
2469#if DEBUG_VIRTUAL_KEYS
2470 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2471 "left=%d, top=%d, right=%d, bottom=%d",
2472 x, y,
2473 virtualKey.keyCode, virtualKey.scanCode,
2474 virtualKey.hitLeft, virtualKey.hitTop,
2475 virtualKey.hitRight, virtualKey.hitBottom);
2476#endif
2477
2478 if (virtualKey.isHit(x, y)) {
2479 return & virtualKey;
2480 }
2481 }
2482
2483 return NULL;
2484}
2485
2486void TouchInputMapper::calculatePointerIds() {
2487 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2488 uint32_t lastPointerCount = mLastTouch.pointerCount;
2489
2490 if (currentPointerCount == 0) {
2491 // No pointers to assign.
2492 mCurrentTouch.idBits.clear();
2493 } else if (lastPointerCount == 0) {
2494 // All pointers are new.
2495 mCurrentTouch.idBits.clear();
2496 for (uint32_t i = 0; i < currentPointerCount; i++) {
2497 mCurrentTouch.pointers[i].id = i;
2498 mCurrentTouch.idToIndex[i] = i;
2499 mCurrentTouch.idBits.markBit(i);
2500 }
2501 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2502 // Only one pointer and no change in count so it must have the same id as before.
2503 uint32_t id = mLastTouch.pointers[0].id;
2504 mCurrentTouch.pointers[0].id = id;
2505 mCurrentTouch.idToIndex[id] = 0;
2506 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2507 } else {
2508 // General case.
2509 // We build a heap of squared euclidean distances between current and last pointers
2510 // associated with the current and last pointer indices. Then, we find the best
2511 // match (by distance) for each current pointer.
2512 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2513
2514 uint32_t heapSize = 0;
2515 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2516 currentPointerIndex++) {
2517 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2518 lastPointerIndex++) {
2519 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2520 - mLastTouch.pointers[lastPointerIndex].x;
2521 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2522 - mLastTouch.pointers[lastPointerIndex].y;
2523
2524 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2525
2526 // Insert new element into the heap (sift up).
2527 heap[heapSize].currentPointerIndex = currentPointerIndex;
2528 heap[heapSize].lastPointerIndex = lastPointerIndex;
2529 heap[heapSize].distance = distance;
2530 heapSize += 1;
2531 }
2532 }
2533
2534 // Heapify
2535 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2536 startIndex -= 1;
2537 for (uint32_t parentIndex = startIndex; ;) {
2538 uint32_t childIndex = parentIndex * 2 + 1;
2539 if (childIndex >= heapSize) {
2540 break;
2541 }
2542
2543 if (childIndex + 1 < heapSize
2544 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2545 childIndex += 1;
2546 }
2547
2548 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2549 break;
2550 }
2551
2552 swap(heap[parentIndex], heap[childIndex]);
2553 parentIndex = childIndex;
2554 }
2555 }
2556
2557#if DEBUG_POINTER_ASSIGNMENT
2558 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2559 for (size_t i = 0; i < heapSize; i++) {
2560 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2561 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2562 heap[i].distance);
2563 }
2564#endif
2565
2566 // Pull matches out by increasing order of distance.
2567 // To avoid reassigning pointers that have already been matched, the loop keeps track
2568 // of which last and current pointers have been matched using the matchedXXXBits variables.
2569 // It also tracks the used pointer id bits.
2570 BitSet32 matchedLastBits(0);
2571 BitSet32 matchedCurrentBits(0);
2572 BitSet32 usedIdBits(0);
2573 bool first = true;
2574 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2575 for (;;) {
2576 if (first) {
2577 // The first time through the loop, we just consume the root element of
2578 // the heap (the one with smallest distance).
2579 first = false;
2580 } else {
2581 // Previous iterations consumed the root element of the heap.
2582 // Pop root element off of the heap (sift down).
2583 heapSize -= 1;
2584 assert(heapSize > 0);
2585
2586 // Sift down.
2587 heap[0] = heap[heapSize];
2588 for (uint32_t parentIndex = 0; ;) {
2589 uint32_t childIndex = parentIndex * 2 + 1;
2590 if (childIndex >= heapSize) {
2591 break;
2592 }
2593
2594 if (childIndex + 1 < heapSize
2595 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2596 childIndex += 1;
2597 }
2598
2599 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2600 break;
2601 }
2602
2603 swap(heap[parentIndex], heap[childIndex]);
2604 parentIndex = childIndex;
2605 }
2606
2607#if DEBUG_POINTER_ASSIGNMENT
2608 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2609 for (size_t i = 0; i < heapSize; i++) {
2610 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2611 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2612 heap[i].distance);
2613 }
2614#endif
2615 }
2616
2617 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2618 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2619
2620 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2621 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2622
2623 matchedCurrentBits.markBit(currentPointerIndex);
2624 matchedLastBits.markBit(lastPointerIndex);
2625
2626 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2627 mCurrentTouch.pointers[currentPointerIndex].id = id;
2628 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2629 usedIdBits.markBit(id);
2630
2631#if DEBUG_POINTER_ASSIGNMENT
2632 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2633 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2634#endif
2635 break;
2636 }
2637 }
2638
2639 // Assign fresh ids to new pointers.
2640 if (currentPointerCount > lastPointerCount) {
2641 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2642 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2643 uint32_t id = usedIdBits.firstUnmarkedBit();
2644
2645 mCurrentTouch.pointers[currentPointerIndex].id = id;
2646 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2647 usedIdBits.markBit(id);
2648
2649#if DEBUG_POINTER_ASSIGNMENT
2650 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2651 currentPointerIndex, id);
2652#endif
2653
2654 if (--i == 0) break; // done
2655 matchedCurrentBits.markBit(currentPointerIndex);
2656 }
2657 }
2658
2659 // Fix id bits.
2660 mCurrentTouch.idBits = usedIdBits;
2661 }
2662}
2663
2664/* Special hack for devices that have bad screen data: if one of the
2665 * points has moved more than a screen height from the last position,
2666 * then drop it. */
2667bool TouchInputMapper::applyBadTouchFilter() {
2668 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002669 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002670 return false;
2671 }
2672
2673 uint32_t pointerCount = mCurrentTouch.pointerCount;
2674
2675 // Nothing to do if there are no points.
2676 if (pointerCount == 0) {
2677 return false;
2678 }
2679
2680 // Don't do anything if a finger is going down or up. We run
2681 // here before assigning pointer IDs, so there isn't a good
2682 // way to do per-finger matching.
2683 if (pointerCount != mLastTouch.pointerCount) {
2684 return false;
2685 }
2686
2687 // We consider a single movement across more than a 7/16 of
2688 // the long size of the screen to be bad. This was a magic value
2689 // determined by looking at the maximum distance it is feasible
2690 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002691 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002692
2693 // XXX The original code in InputDevice.java included commented out
2694 // code for testing the X axis. Note that when we drop a point
2695 // we don't actually restore the old X either. Strange.
2696 // The old code also tries to track when bad points were previously
2697 // detected but it turns out that due to the placement of a "break"
2698 // at the end of the loop, we never set mDroppedBadPoint to true
2699 // so it is effectively dead code.
2700 // Need to figure out if the old code is busted or just overcomplicated
2701 // but working as intended.
2702
2703 // Look through all new points and see if any are farther than
2704 // acceptable from all previous points.
2705 for (uint32_t i = pointerCount; i-- > 0; ) {
2706 int32_t y = mCurrentTouch.pointers[i].y;
2707 int32_t closestY = INT_MAX;
2708 int32_t closestDeltaY = 0;
2709
2710#if DEBUG_HACKS
2711 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2712#endif
2713
2714 for (uint32_t j = pointerCount; j-- > 0; ) {
2715 int32_t lastY = mLastTouch.pointers[j].y;
2716 int32_t deltaY = abs(y - lastY);
2717
2718#if DEBUG_HACKS
2719 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2720 j, lastY, deltaY);
2721#endif
2722
2723 if (deltaY < maxDeltaY) {
2724 goto SkipSufficientlyClosePoint;
2725 }
2726 if (deltaY < closestDeltaY) {
2727 closestDeltaY = deltaY;
2728 closestY = lastY;
2729 }
2730 }
2731
2732 // Must not have found a close enough match.
2733#if DEBUG_HACKS
2734 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2735 i, y, closestY, closestDeltaY, maxDeltaY);
2736#endif
2737
2738 mCurrentTouch.pointers[i].y = closestY;
2739 return true; // XXX original code only corrects one point
2740
2741 SkipSufficientlyClosePoint: ;
2742 }
2743
2744 // No change.
2745 return false;
2746}
2747
2748/* Special hack for devices that have bad screen data: drop points where
2749 * the coordinate value for one axis has jumped to the other pointer's location.
2750 */
2751bool TouchInputMapper::applyJumpyTouchFilter() {
2752 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002753 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002754 return false;
2755 }
2756
2757 uint32_t pointerCount = mCurrentTouch.pointerCount;
2758 if (mLastTouch.pointerCount != pointerCount) {
2759#if DEBUG_HACKS
2760 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2761 mLastTouch.pointerCount, pointerCount);
2762 for (uint32_t i = 0; i < pointerCount; i++) {
2763 LOGD(" Pointer %d (%d, %d)", i,
2764 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2765 }
2766#endif
2767
2768 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2769 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2770 // Just drop the first few events going from 1 to 2 pointers.
2771 // They're bad often enough that they're not worth considering.
2772 mCurrentTouch.pointerCount = 1;
2773 mJumpyTouchFilter.jumpyPointsDropped += 1;
2774
2775#if DEBUG_HACKS
2776 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2777#endif
2778 return true;
2779 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2780 // The event when we go from 2 -> 1 tends to be messed up too
2781 mCurrentTouch.pointerCount = 2;
2782 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2783 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2784 mJumpyTouchFilter.jumpyPointsDropped += 1;
2785
2786#if DEBUG_HACKS
2787 for (int32_t i = 0; i < 2; i++) {
2788 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2789 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2790 }
2791#endif
2792 return true;
2793 }
2794 }
2795 // Reset jumpy points dropped on other transitions or if limit exceeded.
2796 mJumpyTouchFilter.jumpyPointsDropped = 0;
2797
2798#if DEBUG_HACKS
2799 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2800#endif
2801 return false;
2802 }
2803
2804 // We have the same number of pointers as last time.
2805 // A 'jumpy' point is one where the coordinate value for one axis
2806 // has jumped to the other pointer's location. No need to do anything
2807 // else if we only have one pointer.
2808 if (pointerCount < 2) {
2809 return false;
2810 }
2811
2812 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002813 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002814
2815 // We only replace the single worst jumpy point as characterized by pointer distance
2816 // in a single axis.
2817 int32_t badPointerIndex = -1;
2818 int32_t badPointerReplacementIndex = -1;
2819 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2820
2821 for (uint32_t i = pointerCount; i-- > 0; ) {
2822 int32_t x = mCurrentTouch.pointers[i].x;
2823 int32_t y = mCurrentTouch.pointers[i].y;
2824
2825#if DEBUG_HACKS
2826 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2827#endif
2828
2829 // Check if a touch point is too close to another's coordinates
2830 bool dropX = false, dropY = false;
2831 for (uint32_t j = 0; j < pointerCount; j++) {
2832 if (i == j) {
2833 continue;
2834 }
2835
2836 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2837 dropX = true;
2838 break;
2839 }
2840
2841 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2842 dropY = true;
2843 break;
2844 }
2845 }
2846 if (! dropX && ! dropY) {
2847 continue; // not jumpy
2848 }
2849
2850 // Find a replacement candidate by comparing with older points on the
2851 // complementary (non-jumpy) axis.
2852 int32_t distance = INT_MIN; // distance to be corrected
2853 int32_t replacementIndex = -1;
2854
2855 if (dropX) {
2856 // X looks too close. Find an older replacement point with a close Y.
2857 int32_t smallestDeltaY = INT_MAX;
2858 for (uint32_t j = 0; j < pointerCount; j++) {
2859 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2860 if (deltaY < smallestDeltaY) {
2861 smallestDeltaY = deltaY;
2862 replacementIndex = j;
2863 }
2864 }
2865 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2866 } else {
2867 // Y looks too close. Find an older replacement point with a close X.
2868 int32_t smallestDeltaX = INT_MAX;
2869 for (uint32_t j = 0; j < pointerCount; j++) {
2870 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2871 if (deltaX < smallestDeltaX) {
2872 smallestDeltaX = deltaX;
2873 replacementIndex = j;
2874 }
2875 }
2876 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2877 }
2878
2879 // If replacing this pointer would correct a worse error than the previous ones
2880 // considered, then use this replacement instead.
2881 if (distance > badPointerDistance) {
2882 badPointerIndex = i;
2883 badPointerReplacementIndex = replacementIndex;
2884 badPointerDistance = distance;
2885 }
2886 }
2887
2888 // Correct the jumpy pointer if one was found.
2889 if (badPointerIndex >= 0) {
2890#if DEBUG_HACKS
2891 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2892 badPointerIndex,
2893 mLastTouch.pointers[badPointerReplacementIndex].x,
2894 mLastTouch.pointers[badPointerReplacementIndex].y);
2895#endif
2896
2897 mCurrentTouch.pointers[badPointerIndex].x =
2898 mLastTouch.pointers[badPointerReplacementIndex].x;
2899 mCurrentTouch.pointers[badPointerIndex].y =
2900 mLastTouch.pointers[badPointerReplacementIndex].y;
2901 mJumpyTouchFilter.jumpyPointsDropped += 1;
2902 return true;
2903 }
2904 }
2905
2906 mJumpyTouchFilter.jumpyPointsDropped = 0;
2907 return false;
2908}
2909
2910/* Special hack for devices that have bad screen data: aggregate and
2911 * compute averages of the coordinate data, to reduce the amount of
2912 * jitter seen by applications. */
2913void TouchInputMapper::applyAveragingTouchFilter() {
2914 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2915 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2916 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2917 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002918 int32_t pressure;
2919 switch (mCalibration.pressureSource) {
2920 case Calibration::PRESSURE_SOURCE_PRESSURE:
2921 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2922 break;
2923 case Calibration::PRESSURE_SOURCE_TOUCH:
2924 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2925 break;
2926 default:
2927 pressure = 1;
2928 break;
2929 }
Jeff Browne57e8952010-07-23 21:28:06 -07002930
2931 if (mLastTouch.idBits.hasBit(id)) {
2932 // Pointer was down before and is still down now.
2933 // Compute average over history trace.
2934 uint32_t start = mAveragingTouchFilter.historyStart[id];
2935 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2936
2937 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2938 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2939 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2940
2941#if DEBUG_HACKS
2942 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2943 id, distance);
2944#endif
2945
2946 if (distance < AVERAGING_DISTANCE_LIMIT) {
2947 // Increment end index in preparation for recording new historical data.
2948 end += 1;
2949 if (end > AVERAGING_HISTORY_SIZE) {
2950 end = 0;
2951 }
2952
2953 // If the end index has looped back to the start index then we have filled
2954 // the historical trace up to the desired size so we drop the historical
2955 // data at the start of the trace.
2956 if (end == start) {
2957 start += 1;
2958 if (start > AVERAGING_HISTORY_SIZE) {
2959 start = 0;
2960 }
2961 }
2962
2963 // Add the raw data to the historical trace.
2964 mAveragingTouchFilter.historyStart[id] = start;
2965 mAveragingTouchFilter.historyEnd[id] = end;
2966 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2967 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2968 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2969
2970 // Average over all historical positions in the trace by total pressure.
2971 int32_t averagedX = 0;
2972 int32_t averagedY = 0;
2973 int32_t totalPressure = 0;
2974 for (;;) {
2975 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2976 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2977 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2978 .pointers[id].pressure;
2979
2980 averagedX += historicalX * historicalPressure;
2981 averagedY += historicalY * historicalPressure;
2982 totalPressure += historicalPressure;
2983
2984 if (start == end) {
2985 break;
2986 }
2987
2988 start += 1;
2989 if (start > AVERAGING_HISTORY_SIZE) {
2990 start = 0;
2991 }
2992 }
2993
Jeff Brown38a7fab2010-08-30 03:02:23 -07002994 if (totalPressure != 0) {
2995 averagedX /= totalPressure;
2996 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07002997
2998#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07002999 LOGD("AveragingTouchFilter: Pointer id %d - "
3000 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3001 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07003002#endif
3003
Jeff Brown38a7fab2010-08-30 03:02:23 -07003004 mCurrentTouch.pointers[currentIndex].x = averagedX;
3005 mCurrentTouch.pointers[currentIndex].y = averagedY;
3006 }
Jeff Browne57e8952010-07-23 21:28:06 -07003007 } else {
3008#if DEBUG_HACKS
3009 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3010#endif
3011 }
3012 } else {
3013#if DEBUG_HACKS
3014 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3015#endif
3016 }
3017
3018 // Reset pointer history.
3019 mAveragingTouchFilter.historyStart[id] = 0;
3020 mAveragingTouchFilter.historyEnd[id] = 0;
3021 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3022 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3023 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3024 }
3025}
3026
3027int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003028 { // acquire lock
3029 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003030
Jeff Brownb51719b2010-07-29 18:18:33 -07003031 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003032 return AKEY_STATE_VIRTUAL;
3033 }
3034
Jeff Brownb51719b2010-07-29 18:18:33 -07003035 size_t numVirtualKeys = mLocked.virtualKeys.size();
3036 for (size_t i = 0; i < numVirtualKeys; i++) {
3037 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003038 if (virtualKey.keyCode == keyCode) {
3039 return AKEY_STATE_UP;
3040 }
3041 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003042 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003043
3044 return AKEY_STATE_UNKNOWN;
3045}
3046
3047int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003048 { // acquire lock
3049 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003050
Jeff Brownb51719b2010-07-29 18:18:33 -07003051 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003052 return AKEY_STATE_VIRTUAL;
3053 }
3054
Jeff Brownb51719b2010-07-29 18:18:33 -07003055 size_t numVirtualKeys = mLocked.virtualKeys.size();
3056 for (size_t i = 0; i < numVirtualKeys; i++) {
3057 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003058 if (virtualKey.scanCode == scanCode) {
3059 return AKEY_STATE_UP;
3060 }
3061 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003062 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003063
3064 return AKEY_STATE_UNKNOWN;
3065}
3066
3067bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3068 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003069 { // acquire lock
3070 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003071
Jeff Brownb51719b2010-07-29 18:18:33 -07003072 size_t numVirtualKeys = mLocked.virtualKeys.size();
3073 for (size_t i = 0; i < numVirtualKeys; i++) {
3074 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003075
3076 for (size_t i = 0; i < numCodes; i++) {
3077 if (virtualKey.keyCode == keyCodes[i]) {
3078 outFlags[i] = 1;
3079 }
3080 }
3081 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003082 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003083
3084 return true;
3085}
3086
3087
3088// --- SingleTouchInputMapper ---
3089
3090SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3091 TouchInputMapper(device, associatedDisplayId) {
3092 initialize();
3093}
3094
3095SingleTouchInputMapper::~SingleTouchInputMapper() {
3096}
3097
3098void SingleTouchInputMapper::initialize() {
3099 mAccumulator.clear();
3100
3101 mDown = false;
3102 mX = 0;
3103 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003104 mPressure = 0; // default to 0 for devices that don't report pressure
3105 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003106}
3107
3108void SingleTouchInputMapper::reset() {
3109 TouchInputMapper::reset();
3110
Jeff Browne57e8952010-07-23 21:28:06 -07003111 initialize();
3112 }
3113
3114void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3115 switch (rawEvent->type) {
3116 case EV_KEY:
3117 switch (rawEvent->scanCode) {
3118 case BTN_TOUCH:
3119 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3120 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003121 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3122 // not have received valid position information yet. This logic assumes that
3123 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003124 break;
3125 }
3126 break;
3127
3128 case EV_ABS:
3129 switch (rawEvent->scanCode) {
3130 case ABS_X:
3131 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3132 mAccumulator.absX = rawEvent->value;
3133 break;
3134 case ABS_Y:
3135 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3136 mAccumulator.absY = rawEvent->value;
3137 break;
3138 case ABS_PRESSURE:
3139 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3140 mAccumulator.absPressure = rawEvent->value;
3141 break;
3142 case ABS_TOOL_WIDTH:
3143 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3144 mAccumulator.absToolWidth = rawEvent->value;
3145 break;
3146 }
3147 break;
3148
3149 case EV_SYN:
3150 switch (rawEvent->scanCode) {
3151 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003152 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003153 break;
3154 }
3155 break;
3156 }
3157}
3158
3159void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003160 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003161 if (fields == 0) {
3162 return; // no new state changes, so nothing to do
3163 }
Jeff Browne57e8952010-07-23 21:28:06 -07003164
3165 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3166 mDown = mAccumulator.btnTouch;
3167 }
3168
3169 if (fields & Accumulator::FIELD_ABS_X) {
3170 mX = mAccumulator.absX;
3171 }
3172
3173 if (fields & Accumulator::FIELD_ABS_Y) {
3174 mY = mAccumulator.absY;
3175 }
3176
3177 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3178 mPressure = mAccumulator.absPressure;
3179 }
3180
3181 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003182 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003183 }
3184
3185 mCurrentTouch.clear();
3186
3187 if (mDown) {
3188 mCurrentTouch.pointerCount = 1;
3189 mCurrentTouch.pointers[0].id = 0;
3190 mCurrentTouch.pointers[0].x = mX;
3191 mCurrentTouch.pointers[0].y = mY;
3192 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003193 mCurrentTouch.pointers[0].touchMajor = 0;
3194 mCurrentTouch.pointers[0].touchMinor = 0;
3195 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3196 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003197 mCurrentTouch.pointers[0].orientation = 0;
3198 mCurrentTouch.idToIndex[0] = 0;
3199 mCurrentTouch.idBits.markBit(0);
3200 }
3201
3202 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003203
3204 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003205}
3206
Jeff Brown38a7fab2010-08-30 03:02:23 -07003207void SingleTouchInputMapper::configureRawAxes() {
3208 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003209
Jeff Brown38a7fab2010-08-30 03:02:23 -07003210 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3211 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3212 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3213 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003214}
3215
3216
3217// --- MultiTouchInputMapper ---
3218
3219MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3220 TouchInputMapper(device, associatedDisplayId) {
3221 initialize();
3222}
3223
3224MultiTouchInputMapper::~MultiTouchInputMapper() {
3225}
3226
3227void MultiTouchInputMapper::initialize() {
3228 mAccumulator.clear();
3229}
3230
3231void MultiTouchInputMapper::reset() {
3232 TouchInputMapper::reset();
3233
Jeff Browne57e8952010-07-23 21:28:06 -07003234 initialize();
3235}
3236
3237void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3238 switch (rawEvent->type) {
3239 case EV_ABS: {
3240 uint32_t pointerIndex = mAccumulator.pointerCount;
3241 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3242
3243 switch (rawEvent->scanCode) {
3244 case ABS_MT_POSITION_X:
3245 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3246 pointer->absMTPositionX = rawEvent->value;
3247 break;
3248 case ABS_MT_POSITION_Y:
3249 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3250 pointer->absMTPositionY = rawEvent->value;
3251 break;
3252 case ABS_MT_TOUCH_MAJOR:
3253 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3254 pointer->absMTTouchMajor = rawEvent->value;
3255 break;
3256 case ABS_MT_TOUCH_MINOR:
3257 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3258 pointer->absMTTouchMinor = rawEvent->value;
3259 break;
3260 case ABS_MT_WIDTH_MAJOR:
3261 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3262 pointer->absMTWidthMajor = rawEvent->value;
3263 break;
3264 case ABS_MT_WIDTH_MINOR:
3265 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3266 pointer->absMTWidthMinor = rawEvent->value;
3267 break;
3268 case ABS_MT_ORIENTATION:
3269 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3270 pointer->absMTOrientation = rawEvent->value;
3271 break;
3272 case ABS_MT_TRACKING_ID:
3273 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3274 pointer->absMTTrackingId = rawEvent->value;
3275 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003276 case ABS_MT_PRESSURE:
3277 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3278 pointer->absMTPressure = rawEvent->value;
3279 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003280 }
3281 break;
3282 }
3283
3284 case EV_SYN:
3285 switch (rawEvent->scanCode) {
3286 case SYN_MT_REPORT: {
3287 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3288 uint32_t pointerIndex = mAccumulator.pointerCount;
3289
3290 if (mAccumulator.pointers[pointerIndex].fields) {
3291 if (pointerIndex == MAX_POINTERS) {
3292 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3293 MAX_POINTERS);
3294 } else {
3295 pointerIndex += 1;
3296 mAccumulator.pointerCount = pointerIndex;
3297 }
3298 }
3299
3300 mAccumulator.pointers[pointerIndex].clear();
3301 break;
3302 }
3303
3304 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003305 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003306 break;
3307 }
3308 break;
3309 }
3310}
3311
3312void MultiTouchInputMapper::sync(nsecs_t when) {
3313 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003314 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003315
Jeff Browne57e8952010-07-23 21:28:06 -07003316 uint32_t inCount = mAccumulator.pointerCount;
3317 uint32_t outCount = 0;
3318 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003319
Jeff Browne57e8952010-07-23 21:28:06 -07003320 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003321
Jeff Browne57e8952010-07-23 21:28:06 -07003322 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003323 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3324 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003325
Jeff Browne57e8952010-07-23 21:28:06 -07003326 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003327 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3328 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003329 continue;
3330 }
3331
Jeff Brownd64c8552010-08-17 20:38:35 -07003332 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3333 outPointer.x = inPointer.absMTPositionX;
3334 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003335
Jeff Brown38a7fab2010-08-30 03:02:23 -07003336 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3337 if (inPointer.absMTPressure <= 0) {
3338 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brownd64c8552010-08-17 20:38:35 -07003339 // a pointer up. Drop this finger.
3340 continue;
3341 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003342 outPointer.pressure = inPointer.absMTPressure;
3343 } else {
3344 // Default pressure to 0 if absent.
3345 outPointer.pressure = 0;
3346 }
3347
3348 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3349 if (inPointer.absMTTouchMajor <= 0) {
3350 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3351 // a pointer going up. Drop this finger.
3352 continue;
3353 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003354 outPointer.touchMajor = inPointer.absMTTouchMajor;
3355 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003356 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003357 outPointer.touchMajor = 0;
3358 }
Jeff Browne839a582010-04-22 18:58:52 -07003359
Jeff Brownd64c8552010-08-17 20:38:35 -07003360 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3361 outPointer.touchMinor = inPointer.absMTTouchMinor;
3362 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003363 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003364 outPointer.touchMinor = outPointer.touchMajor;
3365 }
Jeff Browne839a582010-04-22 18:58:52 -07003366
Jeff Brownd64c8552010-08-17 20:38:35 -07003367 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3368 outPointer.toolMajor = inPointer.absMTWidthMajor;
3369 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003370 // Default tool area to 0 if absent.
3371 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003372 }
Jeff Browne839a582010-04-22 18:58:52 -07003373
Jeff Brownd64c8552010-08-17 20:38:35 -07003374 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3375 outPointer.toolMinor = inPointer.absMTWidthMinor;
3376 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003377 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003378 outPointer.toolMinor = outPointer.toolMajor;
3379 }
3380
3381 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3382 outPointer.orientation = inPointer.absMTOrientation;
3383 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003384 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003385 outPointer.orientation = 0;
3386 }
3387
Jeff Brown38a7fab2010-08-30 03:02:23 -07003388 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003389 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003390 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3391 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003392
Jeff Browne57e8952010-07-23 21:28:06 -07003393 if (id > MAX_POINTER_ID) {
3394#if DEBUG_POINTERS
3395 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003396 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003397 id, MAX_POINTER_ID);
3398#endif
3399 havePointerIds = false;
3400 }
3401 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003402 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003403 mCurrentTouch.idToIndex[id] = outCount;
3404 mCurrentTouch.idBits.markBit(id);
3405 }
3406 } else {
3407 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003408 }
3409 }
Jeff Browne839a582010-04-22 18:58:52 -07003410
Jeff Browne57e8952010-07-23 21:28:06 -07003411 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003412 }
3413
Jeff Browne57e8952010-07-23 21:28:06 -07003414 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003415
Jeff Browne57e8952010-07-23 21:28:06 -07003416 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003417
3418 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003419}
3420
Jeff Brown38a7fab2010-08-30 03:02:23 -07003421void MultiTouchInputMapper::configureRawAxes() {
3422 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003423
Jeff Brown38a7fab2010-08-30 03:02:23 -07003424 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3425 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3426 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3427 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3428 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3429 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3430 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3431 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003432}
3433
Jeff Browne839a582010-04-22 18:58:52 -07003434
3435} // namespace android