blob: d1674390efd64acf43a59a4476d1ed2bf752cde4 [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brownf4a4ec22010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Browne839a582010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
Jeff Brown38a7fab2010-08-30 03:02:23 -070029#include <stdlib.h>
Jeff Browne839a582010-04-22 18:58:52 -070030#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070031#include <errno.h>
32#include <limits.h>
Jeff Brown5c1ed842010-07-14 18:48:53 -070033#include <math.h>
Jeff Browne839a582010-04-22 18:58:52 -070034
Jeff Brown38a7fab2010-08-30 03:02:23 -070035#define INDENT " "
Jeff Brown26c94ff2010-09-30 14:33:04 -070036#define INDENT2 " "
37#define INDENT3 " "
38#define INDENT4 " "
Jeff Brown38a7fab2010-08-30 03:02:23 -070039
Jeff Browne839a582010-04-22 18:58:52 -070040namespace android {
41
42// --- Static Functions ---
43
44template<typename T>
45inline static T abs(const T& value) {
46 return value < 0 ? - value : value;
47}
48
49template<typename T>
50inline static T min(const T& a, const T& b) {
51 return a < b ? a : b;
52}
53
Jeff Brownf4a4ec22010-06-16 01:53:36 -070054template<typename T>
55inline static void swap(T& a, T& b) {
56 T temp = a;
57 a = b;
58 b = temp;
59}
60
Jeff Brown38a7fab2010-08-30 03:02:23 -070061inline static float avg(float x, float y) {
62 return (x + y) / 2;
63}
64
65inline static float pythag(float x, float y) {
66 return sqrtf(x * x + y * y);
67}
68
Jeff Brown26c94ff2010-09-30 14:33:04 -070069static inline const char* toString(bool value) {
70 return value ? "true" : "false";
71}
72
Jeff Brownf4a4ec22010-06-16 01:53:36 -070073
Jeff Browne839a582010-04-22 18:58:52 -070074int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
75 int32_t mask;
76 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070077 case AKEYCODE_ALT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070078 mask = AMETA_ALT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070079 break;
Jeff Brown8575a872010-06-30 16:10:35 -070080 case AKEYCODE_ALT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070081 mask = AMETA_ALT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070082 break;
Jeff Brown8575a872010-06-30 16:10:35 -070083 case AKEYCODE_SHIFT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070084 mask = AMETA_SHIFT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070085 break;
Jeff Brown8575a872010-06-30 16:10:35 -070086 case AKEYCODE_SHIFT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070087 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070088 break;
Jeff Brown8575a872010-06-30 16:10:35 -070089 case AKEYCODE_SYM:
Jeff Brown5c1ed842010-07-14 18:48:53 -070090 mask = AMETA_SYM_ON;
Jeff Browne839a582010-04-22 18:58:52 -070091 break;
92 default:
93 return oldMetaState;
94 }
95
96 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brown5c1ed842010-07-14 18:48:53 -070097 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Browne839a582010-04-22 18:58:52 -070098
Jeff Brown5c1ed842010-07-14 18:48:53 -070099 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
100 newMetaState |= AMETA_ALT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700101 }
102
Jeff Brown5c1ed842010-07-14 18:48:53 -0700103 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
104 newMetaState |= AMETA_SHIFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700105 }
106
107 return newMetaState;
108}
109
110static const int32_t keyCodeRotationMap[][4] = {
111 // key codes enumerated counter-clockwise with the original (unrotated) key first
112 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brown8575a872010-06-30 16:10:35 -0700113 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
114 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
115 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
116 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Browne839a582010-04-22 18:58:52 -0700117};
118static const int keyCodeRotationMapSize =
119 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
120
121int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700122 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-04-22 18:58:52 -0700123 for (int i = 0; i < keyCodeRotationMapSize; i++) {
124 if (keyCode == keyCodeRotationMap[i][0]) {
125 return keyCodeRotationMap[i][orientation];
126 }
127 }
128 }
129 return keyCode;
130}
131
Jeff Browne57e8952010-07-23 21:28:06 -0700132static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
133 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
134}
135
Jeff Browne839a582010-04-22 18:58:52 -0700136
Jeff Brown38a7fab2010-08-30 03:02:23 -0700137// --- InputDeviceCalibration ---
138
139InputDeviceCalibration::InputDeviceCalibration() {
140}
141
142void InputDeviceCalibration::clear() {
143 mProperties.clear();
144}
145
146void InputDeviceCalibration::addProperty(const String8& key, const String8& value) {
147 mProperties.add(key, value);
148}
149
150bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const {
151 ssize_t index = mProperties.indexOfKey(key);
152 if (index < 0) {
153 return false;
154 }
155
156 outValue = mProperties.valueAt(index);
157 return true;
158}
159
160bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const {
161 String8 stringValue;
162 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
163 return false;
164 }
165
166 char* end;
167 int value = strtol(stringValue.string(), & end, 10);
168 if (*end != '\0') {
169 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.",
170 key.string(), stringValue.string());
171 return false;
172 }
173 outValue = value;
174 return true;
175}
176
177bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const {
178 String8 stringValue;
179 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
180 return false;
181 }
182
183 char* end;
184 float value = strtof(stringValue.string(), & end);
185 if (*end != '\0') {
186 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.",
187 key.string(), stringValue.string());
188 return false;
189 }
190 outValue = value;
191 return true;
192}
193
194
Jeff Browne839a582010-04-22 18:58:52 -0700195// --- InputReader ---
196
197InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700198 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700199 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Browne57e8952010-07-23 21:28:06 -0700200 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
201 mGlobalMetaState(0) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700202 configureExcludedDevices();
Jeff Browne57e8952010-07-23 21:28:06 -0700203 updateGlobalMetaState();
204 updateInputConfiguration();
Jeff Browne839a582010-04-22 18:58:52 -0700205}
206
207InputReader::~InputReader() {
208 for (size_t i = 0; i < mDevices.size(); i++) {
209 delete mDevices.valueAt(i);
210 }
211}
212
213void InputReader::loopOnce() {
214 RawEvent rawEvent;
Jeff Browne57e8952010-07-23 21:28:06 -0700215 mEventHub->getEvent(& rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700216
217#if DEBUG_RAW_EVENTS
218 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
219 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
220 rawEvent.value);
221#endif
222
223 process(& rawEvent);
224}
225
226void InputReader::process(const RawEvent* rawEvent) {
227 switch (rawEvent->type) {
228 case EventHubInterface::DEVICE_ADDED:
Jeff Brown1ad00e92010-10-01 18:55:43 -0700229 addDevice(rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700230 break;
231
232 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown1ad00e92010-10-01 18:55:43 -0700233 removeDevice(rawEvent->deviceId);
234 break;
235
236 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brown3c3cc622010-10-20 15:33:38 -0700237 handleConfigurationChanged(rawEvent->when);
Jeff Browne839a582010-04-22 18:58:52 -0700238 break;
239
Jeff Browne57e8952010-07-23 21:28:06 -0700240 default:
241 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700242 break;
243 }
244}
245
Jeff Brown1ad00e92010-10-01 18:55:43 -0700246void InputReader::addDevice(int32_t deviceId) {
Jeff Browne57e8952010-07-23 21:28:06 -0700247 String8 name = mEventHub->getDeviceName(deviceId);
248 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
249
250 InputDevice* device = createDevice(deviceId, name, classes);
251 device->configure();
252
Jeff Brown38a7fab2010-08-30 03:02:23 -0700253 if (device->isIgnored()) {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700254 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", deviceId, name.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700255 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700256 LOGI("Device added: id=0x%x, name=%s, sources=%08x", deviceId, name.string(),
257 device->getSources());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700258 }
259
Jeff Browne57e8952010-07-23 21:28:06 -0700260 bool added = false;
261 { // acquire device registry writer lock
262 RWLock::AutoWLock _wl(mDeviceRegistryLock);
263
264 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
265 if (deviceIndex < 0) {
266 mDevices.add(deviceId, device);
267 added = true;
268 }
269 } // release device registry writer lock
270
271 if (! added) {
272 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
273 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700274 return;
275 }
Jeff Browne839a582010-04-22 18:58:52 -0700276}
277
Jeff Brown1ad00e92010-10-01 18:55:43 -0700278void InputReader::removeDevice(int32_t deviceId) {
Jeff Browne57e8952010-07-23 21:28:06 -0700279 bool removed = false;
280 InputDevice* device = NULL;
281 { // acquire device registry writer lock
282 RWLock::AutoWLock _wl(mDeviceRegistryLock);
283
284 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
285 if (deviceIndex >= 0) {
286 device = mDevices.valueAt(deviceIndex);
287 mDevices.removeItemsAt(deviceIndex, 1);
288 removed = true;
289 }
290 } // release device registry writer lock
291
292 if (! removed) {
293 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700294 return;
295 }
296
Jeff Browne57e8952010-07-23 21:28:06 -0700297 if (device->isIgnored()) {
298 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
299 device->getId(), device->getName().string());
300 } else {
301 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
302 device->getId(), device->getName().string(), device->getSources());
303 }
304
Jeff Brown38a7fab2010-08-30 03:02:23 -0700305 device->reset();
306
Jeff Browne57e8952010-07-23 21:28:06 -0700307 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700308}
309
Jeff Browne57e8952010-07-23 21:28:06 -0700310InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
311 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Browne839a582010-04-22 18:58:52 -0700312
Jeff Browne57e8952010-07-23 21:28:06 -0700313 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Browne839a582010-04-22 18:58:52 -0700314
Jeff Browne57e8952010-07-23 21:28:06 -0700315 // Switch-like devices.
316 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
317 device->addMapper(new SwitchInputMapper(device));
318 }
319
320 // Keyboard-like devices.
321 uint32_t keyboardSources = 0;
322 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
323 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
324 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
325 }
326 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
327 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
328 }
329 if (classes & INPUT_DEVICE_CLASS_DPAD) {
330 keyboardSources |= AINPUT_SOURCE_DPAD;
331 }
Jeff Browne57e8952010-07-23 21:28:06 -0700332
333 if (keyboardSources != 0) {
334 device->addMapper(new KeyboardInputMapper(device,
335 associatedDisplayId, keyboardSources, keyboardType));
336 }
337
338 // Trackball-like devices.
339 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
340 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
341 }
342
343 // Touchscreen-like devices.
344 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
345 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
346 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
347 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
348 }
349
350 return device;
351}
352
353void InputReader::consumeEvent(const RawEvent* rawEvent) {
354 int32_t deviceId = rawEvent->deviceId;
355
356 { // acquire device registry reader lock
357 RWLock::AutoRLock _rl(mDeviceRegistryLock);
358
359 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
360 if (deviceIndex < 0) {
361 LOGW("Discarding event for unknown deviceId %d.", deviceId);
362 return;
363 }
364
365 InputDevice* device = mDevices.valueAt(deviceIndex);
366 if (device->isIgnored()) {
367 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
368 return;
369 }
370
371 device->process(rawEvent);
372 } // release device registry reader lock
373}
374
Jeff Brown3c3cc622010-10-20 15:33:38 -0700375void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -0700376 // Reset global meta state because it depends on the list of all configured devices.
377 updateGlobalMetaState();
378
379 // Update input configuration.
380 updateInputConfiguration();
381
382 // Enqueue configuration changed.
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
Jeff Browne57e8952010-07-23 21:28:06 -0700798
799// --- SwitchInputMapper ---
800
801SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
802 InputMapper(device) {
803}
804
805SwitchInputMapper::~SwitchInputMapper() {
806}
807
808uint32_t SwitchInputMapper::getSources() {
809 return 0;
810}
811
812void SwitchInputMapper::process(const RawEvent* rawEvent) {
813 switch (rawEvent->type) {
814 case EV_SW:
815 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
816 break;
817 }
818}
819
820void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brown90f0cee2010-10-08 22:31:17 -0700821 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700822}
823
824int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
825 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
826}
827
828
829// --- KeyboardInputMapper ---
830
831KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
832 uint32_t sources, int32_t keyboardType) :
833 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
834 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700835 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700836}
837
838KeyboardInputMapper::~KeyboardInputMapper() {
839}
840
Jeff Brownb51719b2010-07-29 18:18:33 -0700841void KeyboardInputMapper::initializeLocked() {
842 mLocked.metaState = AMETA_NONE;
843 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700844}
845
846uint32_t KeyboardInputMapper::getSources() {
847 return mSources;
848}
849
850void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
851 InputMapper::populateDeviceInfo(info);
852
853 info->setKeyboardType(mKeyboardType);
854}
855
Jeff Brown26c94ff2010-09-30 14:33:04 -0700856void KeyboardInputMapper::dump(String8& dump) {
857 { // acquire lock
858 AutoMutex _l(mLock);
859 dump.append(INDENT2 "Keyboard Input Mapper:\n");
860 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
Jeff Brown26c94ff2010-09-30 14:33:04 -0700861 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
862 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
863 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
864 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
865 } // release lock
866}
867
Jeff Browne57e8952010-07-23 21:28:06 -0700868void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700869 for (;;) {
870 int32_t keyCode, scanCode;
871 { // acquire lock
872 AutoMutex _l(mLock);
873
874 // Synthesize key up event on reset if keys are currently down.
875 if (mLocked.keyDowns.isEmpty()) {
876 initializeLocked();
877 break; // done
878 }
879
880 const KeyDown& keyDown = mLocked.keyDowns.top();
881 keyCode = keyDown.keyCode;
882 scanCode = keyDown.scanCode;
883 } // release lock
884
Jeff Browne57e8952010-07-23 21:28:06 -0700885 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700886 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700887 }
888
889 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700890 getContext()->updateGlobalMetaState();
891}
892
893void KeyboardInputMapper::process(const RawEvent* rawEvent) {
894 switch (rawEvent->type) {
895 case EV_KEY: {
896 int32_t scanCode = rawEvent->scanCode;
897 if (isKeyboardOrGamepadKey(scanCode)) {
898 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
899 rawEvent->flags);
900 }
901 break;
902 }
903 }
904}
905
906bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
907 return scanCode < BTN_MOUSE
908 || scanCode >= KEY_OK
909 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
910}
911
Jeff Brownb51719b2010-07-29 18:18:33 -0700912void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
913 int32_t scanCode, uint32_t policyFlags) {
914 int32_t newMetaState;
915 nsecs_t downTime;
916 bool metaStateChanged = false;
917
918 { // acquire lock
919 AutoMutex _l(mLock);
920
921 if (down) {
922 // Rotate key codes according to orientation if needed.
923 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
924 if (mAssociatedDisplayId >= 0) {
925 int32_t orientation;
926 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
927 return;
928 }
929
930 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700931 }
932
Jeff Brownb51719b2010-07-29 18:18:33 -0700933 // Add key down.
934 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
935 if (keyDownIndex >= 0) {
936 // key repeat, be sure to use same keycode as before in case of rotation
937 keyCode = mLocked.keyDowns.top().keyCode;
938 } else {
939 // key down
940 mLocked.keyDowns.push();
941 KeyDown& keyDown = mLocked.keyDowns.editTop();
942 keyDown.keyCode = keyCode;
943 keyDown.scanCode = scanCode;
944 }
945
946 mLocked.downTime = when;
947 } else {
948 // Remove key down.
949 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
950 if (keyDownIndex >= 0) {
951 // key up, be sure to use same keycode as before in case of rotation
952 keyCode = mLocked.keyDowns.top().keyCode;
953 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
954 } else {
955 // key was not actually down
956 LOGI("Dropping key up from device %s because the key was not down. "
957 "keyCode=%d, scanCode=%d",
958 getDeviceName().string(), keyCode, scanCode);
959 return;
960 }
Jeff Browne57e8952010-07-23 21:28:06 -0700961 }
962
Jeff Brownb51719b2010-07-29 18:18:33 -0700963 int32_t oldMetaState = mLocked.metaState;
964 newMetaState = updateMetaState(keyCode, down, oldMetaState);
965 if (oldMetaState != newMetaState) {
966 mLocked.metaState = newMetaState;
967 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700968 }
Jeff Brown8575a872010-06-30 16:10:35 -0700969
Jeff Brownb51719b2010-07-29 18:18:33 -0700970 downTime = mLocked.downTime;
971 } // release lock
972
973 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700974 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700975 }
976
Jeff Browne57e8952010-07-23 21:28:06 -0700977 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown90f0cee2010-10-08 22:31:17 -0700978 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
979 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700980}
981
Jeff Brownb51719b2010-07-29 18:18:33 -0700982ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
983 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -0700984 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700985 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -0700986 return i;
987 }
988 }
989 return -1;
Jeff Browne839a582010-04-22 18:58:52 -0700990}
991
Jeff Browne57e8952010-07-23 21:28:06 -0700992int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
993 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
994}
Jeff Browne839a582010-04-22 18:58:52 -0700995
Jeff Browne57e8952010-07-23 21:28:06 -0700996int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
997 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
998}
Jeff Browne839a582010-04-22 18:58:52 -0700999
Jeff Browne57e8952010-07-23 21:28:06 -07001000bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1001 const int32_t* keyCodes, uint8_t* outFlags) {
1002 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1003}
1004
1005int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001006 { // acquire lock
1007 AutoMutex _l(mLock);
1008 return mLocked.metaState;
1009 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001010}
1011
1012
1013// --- TrackballInputMapper ---
1014
1015TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1016 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1017 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1018 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1019 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1020 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1021
Jeff Brownb51719b2010-07-29 18:18:33 -07001022 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001023}
1024
1025TrackballInputMapper::~TrackballInputMapper() {
1026}
1027
1028uint32_t TrackballInputMapper::getSources() {
1029 return AINPUT_SOURCE_TRACKBALL;
1030}
1031
1032void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1033 InputMapper::populateDeviceInfo(info);
1034
1035 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1036 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1037}
1038
Jeff Brown26c94ff2010-09-30 14:33:04 -07001039void TrackballInputMapper::dump(String8& dump) {
1040 { // acquire lock
1041 AutoMutex _l(mLock);
1042 dump.append(INDENT2 "Trackball Input Mapper:\n");
1043 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1044 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1045 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1046 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1047 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1048 } // release lock
1049}
1050
Jeff Brownb51719b2010-07-29 18:18:33 -07001051void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001052 mAccumulator.clear();
1053
Jeff Brownb51719b2010-07-29 18:18:33 -07001054 mLocked.down = false;
1055 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001056}
1057
1058void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001059 for (;;) {
1060 { // acquire lock
1061 AutoMutex _l(mLock);
1062
1063 if (! mLocked.down) {
1064 initializeLocked();
1065 break; // done
1066 }
1067 } // release lock
1068
1069 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001070 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001071 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001072 mAccumulator.btnMouse = false;
1073 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001074 }
1075
Jeff Browne57e8952010-07-23 21:28:06 -07001076 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001077}
Jeff Browne839a582010-04-22 18:58:52 -07001078
Jeff Browne57e8952010-07-23 21:28:06 -07001079void TrackballInputMapper::process(const RawEvent* rawEvent) {
1080 switch (rawEvent->type) {
1081 case EV_KEY:
1082 switch (rawEvent->scanCode) {
1083 case BTN_MOUSE:
1084 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1085 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001086 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1087 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001088 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001089 break;
Jeff Browne839a582010-04-22 18:58:52 -07001090 }
Jeff Browne57e8952010-07-23 21:28:06 -07001091 break;
Jeff Browne839a582010-04-22 18:58:52 -07001092
Jeff Browne57e8952010-07-23 21:28:06 -07001093 case EV_REL:
1094 switch (rawEvent->scanCode) {
1095 case REL_X:
1096 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1097 mAccumulator.relX = rawEvent->value;
1098 break;
1099 case REL_Y:
1100 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1101 mAccumulator.relY = rawEvent->value;
1102 break;
Jeff Browne839a582010-04-22 18:58:52 -07001103 }
Jeff Browne57e8952010-07-23 21:28:06 -07001104 break;
Jeff Browne839a582010-04-22 18:58:52 -07001105
Jeff Browne57e8952010-07-23 21:28:06 -07001106 case EV_SYN:
1107 switch (rawEvent->scanCode) {
1108 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001109 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001110 break;
Jeff Browne839a582010-04-22 18:58:52 -07001111 }
Jeff Browne57e8952010-07-23 21:28:06 -07001112 break;
Jeff Browne839a582010-04-22 18:58:52 -07001113 }
Jeff Browne839a582010-04-22 18:58:52 -07001114}
1115
Jeff Browne57e8952010-07-23 21:28:06 -07001116void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001117 uint32_t fields = mAccumulator.fields;
1118 if (fields == 0) {
1119 return; // no new state changes, so nothing to do
1120 }
1121
Jeff Brownb51719b2010-07-29 18:18:33 -07001122 int motionEventAction;
1123 PointerCoords pointerCoords;
1124 nsecs_t downTime;
1125 { // acquire lock
1126 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001127
Jeff Brownb51719b2010-07-29 18:18:33 -07001128 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1129
1130 if (downChanged) {
1131 if (mAccumulator.btnMouse) {
1132 mLocked.down = true;
1133 mLocked.downTime = when;
1134 } else {
1135 mLocked.down = false;
1136 }
Jeff Browne57e8952010-07-23 21:28:06 -07001137 }
Jeff Browne839a582010-04-22 18:58:52 -07001138
Jeff Brownb51719b2010-07-29 18:18:33 -07001139 downTime = mLocked.downTime;
1140 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1141 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001142
Jeff Brownb51719b2010-07-29 18:18:33 -07001143 if (downChanged) {
1144 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001145 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001146 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001147 }
Jeff Browne839a582010-04-22 18:58:52 -07001148
Jeff Brownb51719b2010-07-29 18:18:33 -07001149 pointerCoords.x = x;
1150 pointerCoords.y = y;
1151 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1152 pointerCoords.size = 0;
1153 pointerCoords.touchMajor = 0;
1154 pointerCoords.touchMinor = 0;
1155 pointerCoords.toolMajor = 0;
1156 pointerCoords.toolMinor = 0;
1157 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001158
Jeff Brownb51719b2010-07-29 18:18:33 -07001159 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1160 // Rotate motion based on display orientation if needed.
1161 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1162 int32_t orientation;
1163 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1164 return;
1165 }
1166
1167 float temp;
1168 switch (orientation) {
1169 case InputReaderPolicyInterface::ROTATION_90:
1170 temp = pointerCoords.x;
1171 pointerCoords.x = pointerCoords.y;
1172 pointerCoords.y = - temp;
1173 break;
1174
1175 case InputReaderPolicyInterface::ROTATION_180:
1176 pointerCoords.x = - pointerCoords.x;
1177 pointerCoords.y = - pointerCoords.y;
1178 break;
1179
1180 case InputReaderPolicyInterface::ROTATION_270:
1181 temp = pointerCoords.x;
1182 pointerCoords.x = - pointerCoords.y;
1183 pointerCoords.y = temp;
1184 break;
1185 }
1186 }
1187 } // release lock
1188
Jeff Browne57e8952010-07-23 21:28:06 -07001189 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001190 int32_t pointerId = 0;
Jeff Brown90f0cee2010-10-08 22:31:17 -07001191 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001192 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown90f0cee2010-10-08 22:31:17 -07001193 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1194
1195 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001196}
1197
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001198int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1199 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1200 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1201 } else {
1202 return AKEY_STATE_UNKNOWN;
1203 }
1204}
1205
Jeff Browne57e8952010-07-23 21:28:06 -07001206
1207// --- TouchInputMapper ---
1208
1209TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001210 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1211 mLocked.surfaceOrientation = -1;
1212 mLocked.surfaceWidth = -1;
1213 mLocked.surfaceHeight = -1;
1214
1215 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001216}
1217
1218TouchInputMapper::~TouchInputMapper() {
1219}
1220
1221uint32_t TouchInputMapper::getSources() {
1222 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1223}
1224
1225void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1226 InputMapper::populateDeviceInfo(info);
1227
Jeff Brownb51719b2010-07-29 18:18:33 -07001228 { // acquire lock
1229 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001230
Jeff Brownb51719b2010-07-29 18:18:33 -07001231 // Ensure surface information is up to date so that orientation changes are
1232 // noticed immediately.
1233 configureSurfaceLocked();
1234
1235 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1236 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001237
1238 if (mLocked.orientedRanges.havePressure) {
1239 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1240 mLocked.orientedRanges.pressure);
1241 }
1242
1243 if (mLocked.orientedRanges.haveSize) {
1244 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1245 mLocked.orientedRanges.size);
1246 }
1247
Jeff Brown6b337e72010-10-14 21:42:15 -07001248 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001249 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1250 mLocked.orientedRanges.touchMajor);
1251 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1252 mLocked.orientedRanges.touchMinor);
1253 }
1254
Jeff Brown6b337e72010-10-14 21:42:15 -07001255 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001256 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1257 mLocked.orientedRanges.toolMajor);
1258 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1259 mLocked.orientedRanges.toolMinor);
1260 }
1261
1262 if (mLocked.orientedRanges.haveOrientation) {
1263 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1264 mLocked.orientedRanges.orientation);
1265 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001266 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001267}
1268
Jeff Brown26c94ff2010-09-30 14:33:04 -07001269void TouchInputMapper::dump(String8& dump) {
1270 { // acquire lock
1271 AutoMutex _l(mLock);
1272 dump.append(INDENT2 "Touch Input Mapper:\n");
1273 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1274 dumpParameters(dump);
1275 dumpVirtualKeysLocked(dump);
1276 dumpRawAxes(dump);
1277 dumpCalibration(dump);
1278 dumpSurfaceLocked(dump);
Jeff Brown6b337e72010-10-14 21:42:15 -07001279 dump.appendFormat(INDENT3 "Translation and Scaling Factors:");
1280 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1281 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1282 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1283 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1284 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1285 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1286 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1287 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1288 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1289 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1290 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1291 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1292 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1293 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brown26c94ff2010-09-30 14:33:04 -07001294 } // release lock
1295}
1296
Jeff Brownb51719b2010-07-29 18:18:33 -07001297void TouchInputMapper::initializeLocked() {
1298 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001299 mLastTouch.clear();
1300 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001301
1302 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1303 mAveragingTouchFilter.historyStart[i] = 0;
1304 mAveragingTouchFilter.historyEnd[i] = 0;
1305 }
1306
1307 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001308
1309 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001310
1311 mLocked.orientedRanges.havePressure = false;
1312 mLocked.orientedRanges.haveSize = false;
Jeff Brown6b337e72010-10-14 21:42:15 -07001313 mLocked.orientedRanges.haveTouchSize = false;
1314 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001315 mLocked.orientedRanges.haveOrientation = false;
1316}
1317
Jeff Browne57e8952010-07-23 21:28:06 -07001318void TouchInputMapper::configure() {
1319 InputMapper::configure();
1320
1321 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001322 configureParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001323
1324 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001325 configureRawAxes();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001326
1327 // Prepare input device calibration.
1328 parseCalibration();
1329 resolveCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001330
Jeff Brownb51719b2010-07-29 18:18:33 -07001331 { // acquire lock
1332 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001333
Jeff Brown38a7fab2010-08-30 03:02:23 -07001334 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001335 configureSurfaceLocked();
1336 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001337}
1338
Jeff Brown38a7fab2010-08-30 03:02:23 -07001339void TouchInputMapper::configureParameters() {
1340 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1341 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1342 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1343}
1344
Jeff Brown26c94ff2010-09-30 14:33:04 -07001345void TouchInputMapper::dumpParameters(String8& dump) {
1346 dump.appendFormat(INDENT3 "UseBadTouchFilter: %s\n",
1347 toString(mParameters.useBadTouchFilter));
1348 dump.appendFormat(INDENT3 "UseAveragingTouchFilter: %s\n",
1349 toString(mParameters.useAveragingTouchFilter));
1350 dump.appendFormat(INDENT3 "UseJumpyTouchFilter: %s\n",
1351 toString(mParameters.useJumpyTouchFilter));
Jeff Browna665ca82010-09-08 11:49:43 -07001352}
1353
Jeff Brown38a7fab2010-08-30 03:02:23 -07001354void TouchInputMapper::configureRawAxes() {
1355 mRawAxes.x.clear();
1356 mRawAxes.y.clear();
1357 mRawAxes.pressure.clear();
1358 mRawAxes.touchMajor.clear();
1359 mRawAxes.touchMinor.clear();
1360 mRawAxes.toolMajor.clear();
1361 mRawAxes.toolMinor.clear();
1362 mRawAxes.orientation.clear();
1363}
1364
Jeff Brown26c94ff2010-09-30 14:33:04 -07001365static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Browna665ca82010-09-08 11:49:43 -07001366 if (axis.valid) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001367 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Browna665ca82010-09-08 11:49:43 -07001368 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1369 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001370 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Browna665ca82010-09-08 11:49:43 -07001371 }
1372}
1373
Jeff Brown26c94ff2010-09-30 14:33:04 -07001374void TouchInputMapper::dumpRawAxes(String8& dump) {
1375 dump.append(INDENT3 "Raw Axes:\n");
1376 dumpAxisInfo(dump, mRawAxes.x, "X");
1377 dumpAxisInfo(dump, mRawAxes.y, "Y");
1378 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1379 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1380 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1381 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1382 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1383 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001384}
1385
Jeff Brownb51719b2010-07-29 18:18:33 -07001386bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001387 // Update orientation and dimensions if needed.
1388 int32_t orientation;
1389 int32_t width, height;
1390 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001391 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001392 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1393 return false;
1394 }
1395 } else {
1396 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001397 width = mRawAxes.x.getRange();
1398 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001399 }
1400
Jeff Brownb51719b2010-07-29 18:18:33 -07001401 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001402 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001403 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001404 }
1405
Jeff Brownb51719b2010-07-29 18:18:33 -07001406 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001407 if (sizeChanged) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001408 LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
1409 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001410
Jeff Brownb51719b2010-07-29 18:18:33 -07001411 mLocked.surfaceWidth = width;
1412 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001413
Jeff Brown38a7fab2010-08-30 03:02:23 -07001414 // Configure X and Y factors.
1415 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1416 mLocked.xOrigin = mRawAxes.x.minValue;
1417 mLocked.yOrigin = mRawAxes.y.minValue;
1418 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1419 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001420 mLocked.xPrecision = 1.0f / mLocked.xScale;
1421 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001422
Jeff Brownb51719b2010-07-29 18:18:33 -07001423 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001424 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001425 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001426 mLocked.xOrigin = 0;
1427 mLocked.yOrigin = 0;
1428 mLocked.xScale = 1.0f;
1429 mLocked.yScale = 1.0f;
1430 mLocked.xPrecision = 1.0f;
1431 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001432 }
1433
Jeff Brown38a7fab2010-08-30 03:02:23 -07001434 // Scale factor for terms that are not oriented in a particular axis.
1435 // If the pixels are square then xScale == yScale otherwise we fake it
1436 // by choosing an average.
1437 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001438
Jeff Brown38a7fab2010-08-30 03:02:23 -07001439 // Size of diagonal axis.
1440 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001441
Jeff Brown38a7fab2010-08-30 03:02:23 -07001442 // TouchMajor and TouchMinor factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001443 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1444 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001445 mLocked.orientedRanges.touchMajor.min = 0;
1446 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1447 mLocked.orientedRanges.touchMajor.flat = 0;
1448 mLocked.orientedRanges.touchMajor.fuzz = 0;
1449 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1450 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001451
Jeff Brown38a7fab2010-08-30 03:02:23 -07001452 // ToolMajor and ToolMinor factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001453 mLocked.toolSizeLinearScale = 0;
1454 mLocked.toolSizeLinearBias = 0;
1455 mLocked.toolSizeAreaScale = 0;
1456 mLocked.toolSizeAreaBias = 0;
1457 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1458 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1459 if (mCalibration.haveToolSizeLinearScale) {
1460 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001461 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brown6b337e72010-10-14 21:42:15 -07001462 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown38a7fab2010-08-30 03:02:23 -07001463 / mRawAxes.toolMajor.maxValue;
1464 }
1465
Jeff Brown6b337e72010-10-14 21:42:15 -07001466 if (mCalibration.haveToolSizeLinearBias) {
1467 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1468 }
1469 } else if (mCalibration.toolSizeCalibration ==
1470 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1471 if (mCalibration.haveToolSizeLinearScale) {
1472 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1473 } else {
1474 mLocked.toolSizeLinearScale = min(width, height);
1475 }
1476
1477 if (mCalibration.haveToolSizeLinearBias) {
1478 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1479 }
1480
1481 if (mCalibration.haveToolSizeAreaScale) {
1482 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1483 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1484 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1485 }
1486
1487 if (mCalibration.haveToolSizeAreaBias) {
1488 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001489 }
1490 }
1491
Jeff Brown6b337e72010-10-14 21:42:15 -07001492 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001493 mLocked.orientedRanges.toolMajor.min = 0;
1494 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1495 mLocked.orientedRanges.toolMajor.flat = 0;
1496 mLocked.orientedRanges.toolMajor.fuzz = 0;
1497 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1498 }
1499
1500 // Pressure factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001501 mLocked.pressureScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001502 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1503 RawAbsoluteAxisInfo rawPressureAxis;
1504 switch (mCalibration.pressureSource) {
1505 case Calibration::PRESSURE_SOURCE_PRESSURE:
1506 rawPressureAxis = mRawAxes.pressure;
1507 break;
1508 case Calibration::PRESSURE_SOURCE_TOUCH:
1509 rawPressureAxis = mRawAxes.touchMajor;
1510 break;
1511 default:
1512 rawPressureAxis.clear();
1513 }
1514
Jeff Brown38a7fab2010-08-30 03:02:23 -07001515 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1516 || mCalibration.pressureCalibration
1517 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1518 if (mCalibration.havePressureScale) {
1519 mLocked.pressureScale = mCalibration.pressureScale;
1520 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1521 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1522 }
1523 }
1524
1525 mLocked.orientedRanges.havePressure = true;
1526 mLocked.orientedRanges.pressure.min = 0;
1527 mLocked.orientedRanges.pressure.max = 1.0;
1528 mLocked.orientedRanges.pressure.flat = 0;
1529 mLocked.orientedRanges.pressure.fuzz = 0;
1530 }
1531
1532 // Size factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001533 mLocked.sizeScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001534 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001535 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1536 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1537 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1538 }
1539 }
1540
1541 mLocked.orientedRanges.haveSize = true;
1542 mLocked.orientedRanges.size.min = 0;
1543 mLocked.orientedRanges.size.max = 1.0;
1544 mLocked.orientedRanges.size.flat = 0;
1545 mLocked.orientedRanges.size.fuzz = 0;
1546 }
1547
1548 // Orientation
Jeff Brown6b337e72010-10-14 21:42:15 -07001549 mLocked.orientationScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001550 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001551 if (mCalibration.orientationCalibration
1552 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1553 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1554 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1555 }
1556 }
1557
1558 mLocked.orientedRanges.orientation.min = - M_PI_2;
1559 mLocked.orientedRanges.orientation.max = M_PI_2;
1560 mLocked.orientedRanges.orientation.flat = 0;
1561 mLocked.orientedRanges.orientation.fuzz = 0;
1562 }
Jeff Browne57e8952010-07-23 21:28:06 -07001563 }
1564
1565 if (orientationChanged || sizeChanged) {
1566 // Compute oriented surface dimensions, precision, and scales.
1567 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001568 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001569 case InputReaderPolicyInterface::ROTATION_90:
1570 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001571 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1572 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1573 mLocked.orientedXPrecision = mLocked.yPrecision;
1574 mLocked.orientedYPrecision = mLocked.xPrecision;
1575 orientedXScale = mLocked.yScale;
1576 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001577 break;
1578 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001579 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1580 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1581 mLocked.orientedXPrecision = mLocked.xPrecision;
1582 mLocked.orientedYPrecision = mLocked.yPrecision;
1583 orientedXScale = mLocked.xScale;
1584 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001585 break;
1586 }
1587
1588 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001589 mLocked.orientedRanges.x.min = 0;
1590 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1591 mLocked.orientedRanges.x.flat = 0;
1592 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001593
Jeff Brownb51719b2010-07-29 18:18:33 -07001594 mLocked.orientedRanges.y.min = 0;
1595 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1596 mLocked.orientedRanges.y.flat = 0;
1597 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001598 }
1599
1600 return true;
1601}
1602
Jeff Brown26c94ff2010-09-30 14:33:04 -07001603void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1604 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1605 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1606 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Browna665ca82010-09-08 11:49:43 -07001607}
1608
Jeff Brownb51719b2010-07-29 18:18:33 -07001609void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001610 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001611
Jeff Brownb51719b2010-07-29 18:18:33 -07001612 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001613 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001614 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1615
Jeff Brownb51719b2010-07-29 18:18:33 -07001616 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001617
Jeff Brownb51719b2010-07-29 18:18:33 -07001618 if (virtualKeyDefinitions.size() == 0) {
1619 return;
1620 }
Jeff Browne57e8952010-07-23 21:28:06 -07001621
Jeff Brownb51719b2010-07-29 18:18:33 -07001622 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1623
Jeff Brown38a7fab2010-08-30 03:02:23 -07001624 int32_t touchScreenLeft = mRawAxes.x.minValue;
1625 int32_t touchScreenTop = mRawAxes.y.minValue;
1626 int32_t touchScreenWidth = mRawAxes.x.getRange();
1627 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001628
1629 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001630 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001631 virtualKeyDefinitions[i];
1632
1633 mLocked.virtualKeys.add();
1634 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1635
1636 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1637 int32_t keyCode;
1638 uint32_t flags;
1639 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1640 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001641 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1642 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001643 mLocked.virtualKeys.pop(); // drop the key
1644 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001645 }
1646
Jeff Brownb51719b2010-07-29 18:18:33 -07001647 virtualKey.keyCode = keyCode;
1648 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001649
Jeff Brownb51719b2010-07-29 18:18:33 -07001650 // convert the key definition's display coordinates into touch coordinates for a hit box
1651 int32_t halfWidth = virtualKeyDefinition.width / 2;
1652 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001653
Jeff Brownb51719b2010-07-29 18:18:33 -07001654 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1655 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1656 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1657 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1658 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1659 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1660 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1661 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001662
Jeff Brown26c94ff2010-09-30 14:33:04 -07001663 }
1664}
1665
1666void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1667 if (!mLocked.virtualKeys.isEmpty()) {
1668 dump.append(INDENT3 "Virtual Keys:\n");
1669
1670 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1671 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1672 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1673 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1674 i, virtualKey.scanCode, virtualKey.keyCode,
1675 virtualKey.hitLeft, virtualKey.hitRight,
1676 virtualKey.hitTop, virtualKey.hitBottom);
1677 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001678 }
Jeff Browne57e8952010-07-23 21:28:06 -07001679}
1680
Jeff Brown38a7fab2010-08-30 03:02:23 -07001681void TouchInputMapper::parseCalibration() {
1682 const InputDeviceCalibration& in = getDevice()->getCalibration();
1683 Calibration& out = mCalibration;
1684
Jeff Brown6b337e72010-10-14 21:42:15 -07001685 // Touch Size
1686 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1687 String8 touchSizeCalibrationString;
1688 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1689 if (touchSizeCalibrationString == "none") {
1690 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1691 } else if (touchSizeCalibrationString == "geometric") {
1692 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1693 } else if (touchSizeCalibrationString == "pressure") {
1694 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1695 } else if (touchSizeCalibrationString != "default") {
1696 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1697 touchSizeCalibrationString.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -07001698 }
1699 }
1700
Jeff Brown6b337e72010-10-14 21:42:15 -07001701 // Tool Size
1702 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1703 String8 toolSizeCalibrationString;
1704 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1705 if (toolSizeCalibrationString == "none") {
1706 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1707 } else if (toolSizeCalibrationString == "geometric") {
1708 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1709 } else if (toolSizeCalibrationString == "linear") {
1710 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1711 } else if (toolSizeCalibrationString == "area") {
1712 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1713 } else if (toolSizeCalibrationString != "default") {
1714 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1715 toolSizeCalibrationString.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -07001716 }
1717 }
1718
Jeff Brown6b337e72010-10-14 21:42:15 -07001719 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1720 out.toolSizeLinearScale);
1721 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1722 out.toolSizeLinearBias);
1723 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1724 out.toolSizeAreaScale);
1725 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1726 out.toolSizeAreaBias);
1727 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1728 out.toolSizeIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001729
1730 // Pressure
1731 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1732 String8 pressureCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001733 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001734 if (pressureCalibrationString == "none") {
1735 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1736 } else if (pressureCalibrationString == "physical") {
1737 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1738 } else if (pressureCalibrationString == "amplitude") {
1739 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1740 } else if (pressureCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001741 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001742 pressureCalibrationString.string());
1743 }
1744 }
1745
1746 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1747 String8 pressureSourceString;
1748 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1749 if (pressureSourceString == "pressure") {
1750 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1751 } else if (pressureSourceString == "touch") {
1752 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1753 } else if (pressureSourceString != "default") {
1754 LOGW("Invalid value for touch.pressure.source: '%s'",
1755 pressureSourceString.string());
1756 }
1757 }
1758
1759 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1760 out.pressureScale);
1761
1762 // Size
1763 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1764 String8 sizeCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001765 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001766 if (sizeCalibrationString == "none") {
1767 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1768 } else if (sizeCalibrationString == "normalized") {
1769 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1770 } else if (sizeCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001771 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001772 sizeCalibrationString.string());
1773 }
1774 }
1775
1776 // Orientation
1777 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1778 String8 orientationCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001779 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001780 if (orientationCalibrationString == "none") {
1781 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1782 } else if (orientationCalibrationString == "interpolated") {
1783 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1784 } else if (orientationCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001785 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001786 orientationCalibrationString.string());
1787 }
1788 }
1789}
1790
1791void TouchInputMapper::resolveCalibration() {
1792 // Pressure
1793 switch (mCalibration.pressureSource) {
1794 case Calibration::PRESSURE_SOURCE_DEFAULT:
1795 if (mRawAxes.pressure.valid) {
1796 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1797 } else if (mRawAxes.touchMajor.valid) {
1798 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1799 }
1800 break;
1801
1802 case Calibration::PRESSURE_SOURCE_PRESSURE:
1803 if (! mRawAxes.pressure.valid) {
1804 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1805 "the pressure axis is not available.");
1806 }
1807 break;
1808
1809 case Calibration::PRESSURE_SOURCE_TOUCH:
1810 if (! mRawAxes.touchMajor.valid) {
1811 LOGW("Calibration property touch.pressure.source is 'touch' but "
1812 "the touchMajor axis is not available.");
1813 }
1814 break;
1815
1816 default:
1817 break;
1818 }
1819
1820 switch (mCalibration.pressureCalibration) {
1821 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1822 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1823 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1824 } else {
1825 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1826 }
1827 break;
1828
1829 default:
1830 break;
1831 }
1832
Jeff Brown6b337e72010-10-14 21:42:15 -07001833 // Tool Size
1834 switch (mCalibration.toolSizeCalibration) {
1835 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown38a7fab2010-08-30 03:02:23 -07001836 if (mRawAxes.toolMajor.valid) {
Jeff Brown6b337e72010-10-14 21:42:15 -07001837 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001838 } else {
Jeff Brown6b337e72010-10-14 21:42:15 -07001839 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001840 }
1841 break;
1842
1843 default:
1844 break;
1845 }
1846
Jeff Brown6b337e72010-10-14 21:42:15 -07001847 // Touch Size
1848 switch (mCalibration.touchSizeCalibration) {
1849 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown38a7fab2010-08-30 03:02:23 -07001850 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brown6b337e72010-10-14 21:42:15 -07001851 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1852 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001853 } else {
Jeff Brown6b337e72010-10-14 21:42:15 -07001854 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001855 }
1856 break;
1857
1858 default:
1859 break;
1860 }
1861
1862 // Size
1863 switch (mCalibration.sizeCalibration) {
1864 case Calibration::SIZE_CALIBRATION_DEFAULT:
1865 if (mRawAxes.toolMajor.valid) {
1866 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1867 } else {
1868 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1869 }
1870 break;
1871
1872 default:
1873 break;
1874 }
1875
1876 // Orientation
1877 switch (mCalibration.orientationCalibration) {
1878 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1879 if (mRawAxes.orientation.valid) {
1880 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1881 } else {
1882 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1883 }
1884 break;
1885
1886 default:
1887 break;
1888 }
1889}
1890
Jeff Brown26c94ff2010-09-30 14:33:04 -07001891void TouchInputMapper::dumpCalibration(String8& dump) {
1892 dump.append(INDENT3 "Calibration:\n");
Jeff Browna665ca82010-09-08 11:49:43 -07001893
Jeff Brown6b337e72010-10-14 21:42:15 -07001894 // Touch Size
1895 switch (mCalibration.touchSizeCalibration) {
1896 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
1897 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001898 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001899 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
1900 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001901 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001902 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
1903 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001904 break;
1905 default:
1906 assert(false);
1907 }
1908
Jeff Brown6b337e72010-10-14 21:42:15 -07001909 // Tool Size
1910 switch (mCalibration.toolSizeCalibration) {
1911 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
1912 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001913 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001914 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
1915 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001916 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001917 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
1918 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
1919 break;
1920 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
1921 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001922 break;
1923 default:
1924 assert(false);
1925 }
1926
Jeff Brown6b337e72010-10-14 21:42:15 -07001927 if (mCalibration.haveToolSizeLinearScale) {
1928 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
1929 mCalibration.toolSizeLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001930 }
1931
Jeff Brown6b337e72010-10-14 21:42:15 -07001932 if (mCalibration.haveToolSizeLinearBias) {
1933 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
1934 mCalibration.toolSizeLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001935 }
1936
Jeff Brown6b337e72010-10-14 21:42:15 -07001937 if (mCalibration.haveToolSizeAreaScale) {
1938 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
1939 mCalibration.toolSizeAreaScale);
1940 }
1941
1942 if (mCalibration.haveToolSizeAreaBias) {
1943 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
1944 mCalibration.toolSizeAreaBias);
1945 }
1946
1947 if (mCalibration.haveToolSizeIsSummed) {
1948 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %d\n",
1949 mCalibration.toolSizeIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001950 }
1951
1952 // Pressure
1953 switch (mCalibration.pressureCalibration) {
1954 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001955 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001956 break;
1957 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001958 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001959 break;
1960 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001961 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001962 break;
1963 default:
1964 assert(false);
1965 }
1966
1967 switch (mCalibration.pressureSource) {
1968 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001969 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001970 break;
1971 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001972 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001973 break;
1974 case Calibration::PRESSURE_SOURCE_DEFAULT:
1975 break;
1976 default:
1977 assert(false);
1978 }
1979
1980 if (mCalibration.havePressureScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001981 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
1982 mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001983 }
1984
1985 // Size
1986 switch (mCalibration.sizeCalibration) {
1987 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001988 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001989 break;
1990 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001991 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001992 break;
1993 default:
1994 assert(false);
1995 }
1996
1997 // Orientation
1998 switch (mCalibration.orientationCalibration) {
1999 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002000 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002001 break;
2002 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002003 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002004 break;
2005 default:
2006 assert(false);
2007 }
2008}
2009
Jeff Browne57e8952010-07-23 21:28:06 -07002010void TouchInputMapper::reset() {
2011 // Synthesize touch up event if touch is currently down.
2012 // This will also take care of finishing virtual key processing if needed.
2013 if (mLastTouch.pointerCount != 0) {
2014 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2015 mCurrentTouch.clear();
2016 syncTouch(when, true);
2017 }
2018
Jeff Brownb51719b2010-07-29 18:18:33 -07002019 { // acquire lock
2020 AutoMutex _l(mLock);
2021 initializeLocked();
2022 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002023
Jeff Brownb51719b2010-07-29 18:18:33 -07002024 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07002025}
2026
2027void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Browne839a582010-04-22 18:58:52 -07002028 uint32_t policyFlags = 0;
Jeff Browne839a582010-04-22 18:58:52 -07002029
Jeff Brownb51719b2010-07-29 18:18:33 -07002030 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07002031
Jeff Browne57e8952010-07-23 21:28:06 -07002032 if (mParameters.useBadTouchFilter) {
2033 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002034 havePointerIds = false;
2035 }
2036 }
2037
Jeff Browne57e8952010-07-23 21:28:06 -07002038 if (mParameters.useJumpyTouchFilter) {
2039 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002040 havePointerIds = false;
2041 }
2042 }
2043
2044 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002045 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002046 }
2047
Jeff Browne57e8952010-07-23 21:28:06 -07002048 TouchData temp;
2049 TouchData* savedTouch;
2050 if (mParameters.useAveragingTouchFilter) {
2051 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002052 savedTouch = & temp;
2053
Jeff Browne57e8952010-07-23 21:28:06 -07002054 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002055 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002056 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002057 }
2058
Jeff Brownb51719b2010-07-29 18:18:33 -07002059 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002060
Jeff Browne57e8952010-07-23 21:28:06 -07002061 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2062 if (touchResult == DISPATCH_TOUCH) {
2063 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002064 }
2065
Jeff Brownb51719b2010-07-29 18:18:33 -07002066 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002067
Jeff Browne57e8952010-07-23 21:28:06 -07002068 if (touchResult == DROP_STROKE) {
2069 mLastTouch.clear();
2070 } else {
2071 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002072 }
Jeff Browne839a582010-04-22 18:58:52 -07002073}
2074
Jeff Browne57e8952010-07-23 21:28:06 -07002075TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2076 nsecs_t when, uint32_t policyFlags) {
2077 int32_t keyEventAction, keyEventFlags;
2078 int32_t keyCode, scanCode, downTime;
2079 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002080
Jeff Brownb51719b2010-07-29 18:18:33 -07002081 { // acquire lock
2082 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002083
Jeff Brownb51719b2010-07-29 18:18:33 -07002084 // Update surface size and orientation, including virtual key positions.
2085 if (! configureSurfaceLocked()) {
2086 return DROP_STROKE;
2087 }
2088
2089 // Check for virtual key press.
2090 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002091 if (mCurrentTouch.pointerCount == 0) {
2092 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002093 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002094#if DEBUG_VIRTUAL_KEYS
2095 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brown3c3cc622010-10-20 15:33:38 -07002096 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Browne57e8952010-07-23 21:28:06 -07002097#endif
2098 keyEventAction = AKEY_EVENT_ACTION_UP;
2099 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2100 touchResult = SKIP_TOUCH;
2101 goto DispatchVirtualKey;
2102 }
2103
2104 if (mCurrentTouch.pointerCount == 1) {
2105 int32_t x = mCurrentTouch.pointers[0].x;
2106 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002107 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2108 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002109 // Pointer is still within the space of the virtual key.
2110 return SKIP_TOUCH;
2111 }
2112 }
2113
2114 // Pointer left virtual key area or another pointer also went down.
2115 // Send key cancellation and drop the stroke so subsequent motions will be
2116 // considered fresh downs. This is useful when the user swipes away from the
2117 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002118 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002119#if DEBUG_VIRTUAL_KEYS
2120 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brown3c3cc622010-10-20 15:33:38 -07002121 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Browne57e8952010-07-23 21:28:06 -07002122#endif
2123 keyEventAction = AKEY_EVENT_ACTION_UP;
2124 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2125 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brown3c3cc622010-10-20 15:33:38 -07002126
2127 // Check whether the pointer moved inside the display area where we should
2128 // start a new stroke.
2129 int32_t x = mCurrentTouch.pointers[0].x;
2130 int32_t y = mCurrentTouch.pointers[0].y;
2131 if (isPointInsideSurfaceLocked(x, y)) {
2132 mLastTouch.clear();
2133 touchResult = DISPATCH_TOUCH;
2134 } else {
2135 touchResult = DROP_STROKE;
2136 }
Jeff Browne57e8952010-07-23 21:28:06 -07002137 } else {
2138 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2139 // Pointer just went down. Handle off-screen touches, if needed.
2140 int32_t x = mCurrentTouch.pointers[0].x;
2141 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002142 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002143 // If exactly one pointer went down, check for virtual key hit.
2144 // Otherwise we will drop the entire stroke.
2145 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002146 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002147 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002148 mLocked.currentVirtualKey.down = true;
2149 mLocked.currentVirtualKey.downTime = when;
2150 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2151 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002152#if DEBUG_VIRTUAL_KEYS
2153 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brown3c3cc622010-10-20 15:33:38 -07002154 mLocked.currentVirtualKey.keyCode,
2155 mLocked.currentVirtualKey.scanCode);
Jeff Browne57e8952010-07-23 21:28:06 -07002156#endif
2157 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2158 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2159 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2160 touchResult = SKIP_TOUCH;
2161 goto DispatchVirtualKey;
2162 }
2163 }
2164 return DROP_STROKE;
2165 }
2166 }
2167 return DISPATCH_TOUCH;
2168 }
2169
2170 DispatchVirtualKey:
2171 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002172 keyCode = mLocked.currentVirtualKey.keyCode;
2173 scanCode = mLocked.currentVirtualKey.scanCode;
2174 downTime = mLocked.currentVirtualKey.downTime;
2175 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002176
2177 // Dispatch virtual key.
2178 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown956c0fb2010-10-01 14:55:30 -07002179 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brown90f0cee2010-10-08 22:31:17 -07002180 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2181 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2182 return touchResult;
Jeff Browne839a582010-04-22 18:58:52 -07002183}
2184
Jeff Browne57e8952010-07-23 21:28:06 -07002185void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2186 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2187 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002188 if (currentPointerCount == 0 && lastPointerCount == 0) {
2189 return; // nothing to do!
2190 }
2191
Jeff Browne57e8952010-07-23 21:28:06 -07002192 BitSet32 currentIdBits = mCurrentTouch.idBits;
2193 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002194
2195 if (currentIdBits == lastIdBits) {
2196 // No pointer id changes so this is a move event.
2197 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002198 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002199 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002200 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002201 } else {
Jeff Brown3c3cc622010-10-20 15:33:38 -07002202 // There may be pointers going up and pointers going down and pointers moving
2203 // all at the same time.
Jeff Browne839a582010-04-22 18:58:52 -07002204 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2205 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2206 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002207 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002208
Jeff Brown3c3cc622010-10-20 15:33:38 -07002209 // Produce an intermediate representation of the touch data that consists of the
2210 // old location of pointers that have just gone up and the new location of pointers that
2211 // have just moved but omits the location of pointers that have just gone down.
2212 TouchData interimTouch;
2213 interimTouch.copyFrom(mLastTouch);
2214
2215 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2216 bool moveNeeded = false;
2217 while (!moveIdBits.isEmpty()) {
2218 uint32_t moveId = moveIdBits.firstMarkedBit();
2219 moveIdBits.clearBit(moveId);
2220
2221 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2222 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2223 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2224 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2225 moveNeeded = true;
2226 }
2227 }
2228
2229 // Dispatch pointer up events using the interim pointer locations.
2230 while (!upIdBits.isEmpty()) {
Jeff Browne839a582010-04-22 18:58:52 -07002231 uint32_t upId = upIdBits.firstMarkedBit();
2232 upIdBits.clearBit(upId);
2233 BitSet32 oldActiveIdBits = activeIdBits;
2234 activeIdBits.clearBit(upId);
2235
2236 int32_t motionEventAction;
2237 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002238 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002239 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002240 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002241 }
2242
Jeff Brown3c3cc622010-10-20 15:33:38 -07002243 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002244 oldActiveIdBits, upId, pointerCount, motionEventAction);
2245 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002246 }
2247
Jeff Brown3c3cc622010-10-20 15:33:38 -07002248 // Dispatch move events if any of the remaining pointers moved from their old locations.
2249 // Although applications receive new locations as part of individual pointer up
2250 // events, they do not generally handle them except when presented in a move event.
2251 if (moveNeeded) {
2252 dispatchTouch(when, policyFlags, &mCurrentTouch,
2253 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2254 }
2255
2256 // Dispatch pointer down events using the new pointer locations.
2257 while (!downIdBits.isEmpty()) {
Jeff Browne839a582010-04-22 18:58:52 -07002258 uint32_t downId = downIdBits.firstMarkedBit();
2259 downIdBits.clearBit(downId);
2260 BitSet32 oldActiveIdBits = activeIdBits;
2261 activeIdBits.markBit(downId);
2262
2263 int32_t motionEventAction;
2264 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002265 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002266 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002267 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002268 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002269 }
2270
Jeff Brown38a7fab2010-08-30 03:02:23 -07002271 pointerCount += 1;
Jeff Brown3c3cc622010-10-20 15:33:38 -07002272 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002273 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002274 }
2275 }
2276}
2277
Jeff Browne57e8952010-07-23 21:28:06 -07002278void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002279 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002280 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002281 int32_t pointerIds[MAX_POINTERS];
2282 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002283 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002284 float xPrecision, yPrecision;
2285
2286 { // acquire lock
2287 AutoMutex _l(mLock);
2288
2289 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2290 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002291 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002292 uint32_t id = idBits.firstMarkedBit();
2293 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002294 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002295
Jeff Brown38a7fab2010-08-30 03:02:23 -07002296 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002297
Jeff Brown38a7fab2010-08-30 03:02:23 -07002298 // X and Y
2299 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2300 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002301
Jeff Brown38a7fab2010-08-30 03:02:23 -07002302 // ToolMajor and ToolMinor
2303 float toolMajor, toolMinor;
Jeff Brown6b337e72010-10-14 21:42:15 -07002304 switch (mCalibration.toolSizeCalibration) {
2305 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002306 toolMajor = in.toolMajor * mLocked.geometricScale;
2307 if (mRawAxes.toolMinor.valid) {
2308 toolMinor = in.toolMinor * mLocked.geometricScale;
2309 } else {
2310 toolMinor = toolMajor;
2311 }
2312 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002313 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002314 toolMajor = in.toolMajor != 0
Jeff Brown6b337e72010-10-14 21:42:15 -07002315 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown38a7fab2010-08-30 03:02:23 -07002316 : 0;
2317 if (mRawAxes.toolMinor.valid) {
2318 toolMinor = in.toolMinor != 0
Jeff Brown6b337e72010-10-14 21:42:15 -07002319 ? in.toolMinor * mLocked.toolSizeLinearScale
2320 + mLocked.toolSizeLinearBias
Jeff Brown38a7fab2010-08-30 03:02:23 -07002321 : 0;
2322 } else {
2323 toolMinor = toolMajor;
2324 }
2325 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002326 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2327 if (in.toolMajor != 0) {
2328 float diameter = sqrtf(in.toolMajor
2329 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2330 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2331 } else {
2332 toolMajor = 0;
2333 }
2334 toolMinor = toolMajor;
2335 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002336 default:
2337 toolMajor = 0;
2338 toolMinor = 0;
2339 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002340 }
2341
Jeff Brown6b337e72010-10-14 21:42:15 -07002342 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002343 toolMajor /= pointerCount;
2344 toolMinor /= pointerCount;
2345 }
2346
2347 // Pressure
2348 float rawPressure;
2349 switch (mCalibration.pressureSource) {
2350 case Calibration::PRESSURE_SOURCE_PRESSURE:
2351 rawPressure = in.pressure;
2352 break;
2353 case Calibration::PRESSURE_SOURCE_TOUCH:
2354 rawPressure = in.touchMajor;
2355 break;
2356 default:
2357 rawPressure = 0;
2358 }
2359
2360 float pressure;
2361 switch (mCalibration.pressureCalibration) {
2362 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2363 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2364 pressure = rawPressure * mLocked.pressureScale;
2365 break;
2366 default:
2367 pressure = 1;
2368 break;
2369 }
2370
2371 // TouchMajor and TouchMinor
2372 float touchMajor, touchMinor;
Jeff Brown6b337e72010-10-14 21:42:15 -07002373 switch (mCalibration.touchSizeCalibration) {
2374 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002375 touchMajor = in.touchMajor * mLocked.geometricScale;
2376 if (mRawAxes.touchMinor.valid) {
2377 touchMinor = in.touchMinor * mLocked.geometricScale;
2378 } else {
2379 touchMinor = touchMajor;
2380 }
2381 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002382 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002383 touchMajor = toolMajor * pressure;
2384 touchMinor = toolMinor * pressure;
2385 break;
2386 default:
2387 touchMajor = 0;
2388 touchMinor = 0;
2389 break;
2390 }
2391
2392 if (touchMajor > toolMajor) {
2393 touchMajor = toolMajor;
2394 }
2395 if (touchMinor > toolMinor) {
2396 touchMinor = toolMinor;
2397 }
2398
2399 // Size
2400 float size;
2401 switch (mCalibration.sizeCalibration) {
2402 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2403 float rawSize = mRawAxes.toolMinor.valid
2404 ? avg(in.toolMajor, in.toolMinor)
2405 : in.toolMajor;
2406 size = rawSize * mLocked.sizeScale;
2407 break;
2408 }
2409 default:
2410 size = 0;
2411 break;
2412 }
2413
2414 // Orientation
2415 float orientation;
2416 switch (mCalibration.orientationCalibration) {
2417 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2418 orientation = in.orientation * mLocked.orientationScale;
2419 break;
2420 default:
2421 orientation = 0;
2422 }
2423
2424 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002425 switch (mLocked.surfaceOrientation) {
2426 case InputReaderPolicyInterface::ROTATION_90: {
2427 float xTemp = x;
2428 x = y;
2429 y = mLocked.surfaceWidth - xTemp;
2430 orientation -= M_PI_2;
2431 if (orientation < - M_PI_2) {
2432 orientation += M_PI;
2433 }
2434 break;
2435 }
2436 case InputReaderPolicyInterface::ROTATION_180: {
2437 x = mLocked.surfaceWidth - x;
2438 y = mLocked.surfaceHeight - y;
2439 orientation = - orientation;
2440 break;
2441 }
2442 case InputReaderPolicyInterface::ROTATION_270: {
2443 float xTemp = x;
2444 x = mLocked.surfaceHeight - y;
2445 y = xTemp;
2446 orientation += M_PI_2;
2447 if (orientation > M_PI_2) {
2448 orientation -= M_PI;
2449 }
2450 break;
2451 }
2452 }
2453
Jeff Brown38a7fab2010-08-30 03:02:23 -07002454 // Write output coords.
2455 PointerCoords& out = pointerCoords[outIndex];
2456 out.x = x;
2457 out.y = y;
2458 out.pressure = pressure;
2459 out.size = size;
2460 out.touchMajor = touchMajor;
2461 out.touchMinor = touchMinor;
2462 out.toolMajor = toolMajor;
2463 out.toolMinor = toolMinor;
2464 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002465
Jeff Brown38a7fab2010-08-30 03:02:23 -07002466 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002467
2468 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002469 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002470 }
Jeff Browne839a582010-04-22 18:58:52 -07002471 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002472
2473 // Check edge flags by looking only at the first pointer since the flags are
2474 // global to the event.
2475 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2476 if (pointerCoords[0].x <= 0) {
2477 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2478 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2479 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2480 }
2481 if (pointerCoords[0].y <= 0) {
2482 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2483 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2484 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2485 }
Jeff Browne839a582010-04-22 18:58:52 -07002486 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002487
2488 xPrecision = mLocked.orientedXPrecision;
2489 yPrecision = mLocked.orientedYPrecision;
2490 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002491
Jeff Brown77e26fc2010-10-07 13:44:51 -07002492 getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002493 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002494 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002495 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002496}
2497
Jeff Brownb51719b2010-07-29 18:18:33 -07002498bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002499 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2500 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2501 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002502 }
Jeff Browne57e8952010-07-23 21:28:06 -07002503 return true;
2504}
2505
Jeff Brownb51719b2010-07-29 18:18:33 -07002506const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2507 int32_t x, int32_t y) {
2508 size_t numVirtualKeys = mLocked.virtualKeys.size();
2509 for (size_t i = 0; i < numVirtualKeys; i++) {
2510 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002511
2512#if DEBUG_VIRTUAL_KEYS
2513 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2514 "left=%d, top=%d, right=%d, bottom=%d",
2515 x, y,
2516 virtualKey.keyCode, virtualKey.scanCode,
2517 virtualKey.hitLeft, virtualKey.hitTop,
2518 virtualKey.hitRight, virtualKey.hitBottom);
2519#endif
2520
2521 if (virtualKey.isHit(x, y)) {
2522 return & virtualKey;
2523 }
2524 }
2525
2526 return NULL;
2527}
2528
2529void TouchInputMapper::calculatePointerIds() {
2530 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2531 uint32_t lastPointerCount = mLastTouch.pointerCount;
2532
2533 if (currentPointerCount == 0) {
2534 // No pointers to assign.
2535 mCurrentTouch.idBits.clear();
2536 } else if (lastPointerCount == 0) {
2537 // All pointers are new.
2538 mCurrentTouch.idBits.clear();
2539 for (uint32_t i = 0; i < currentPointerCount; i++) {
2540 mCurrentTouch.pointers[i].id = i;
2541 mCurrentTouch.idToIndex[i] = i;
2542 mCurrentTouch.idBits.markBit(i);
2543 }
2544 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2545 // Only one pointer and no change in count so it must have the same id as before.
2546 uint32_t id = mLastTouch.pointers[0].id;
2547 mCurrentTouch.pointers[0].id = id;
2548 mCurrentTouch.idToIndex[id] = 0;
2549 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2550 } else {
2551 // General case.
2552 // We build a heap of squared euclidean distances between current and last pointers
2553 // associated with the current and last pointer indices. Then, we find the best
2554 // match (by distance) for each current pointer.
2555 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2556
2557 uint32_t heapSize = 0;
2558 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2559 currentPointerIndex++) {
2560 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2561 lastPointerIndex++) {
2562 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2563 - mLastTouch.pointers[lastPointerIndex].x;
2564 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2565 - mLastTouch.pointers[lastPointerIndex].y;
2566
2567 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2568
2569 // Insert new element into the heap (sift up).
2570 heap[heapSize].currentPointerIndex = currentPointerIndex;
2571 heap[heapSize].lastPointerIndex = lastPointerIndex;
2572 heap[heapSize].distance = distance;
2573 heapSize += 1;
2574 }
2575 }
2576
2577 // Heapify
2578 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2579 startIndex -= 1;
2580 for (uint32_t parentIndex = startIndex; ;) {
2581 uint32_t childIndex = parentIndex * 2 + 1;
2582 if (childIndex >= heapSize) {
2583 break;
2584 }
2585
2586 if (childIndex + 1 < heapSize
2587 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2588 childIndex += 1;
2589 }
2590
2591 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2592 break;
2593 }
2594
2595 swap(heap[parentIndex], heap[childIndex]);
2596 parentIndex = childIndex;
2597 }
2598 }
2599
2600#if DEBUG_POINTER_ASSIGNMENT
2601 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2602 for (size_t i = 0; i < heapSize; i++) {
2603 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2604 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2605 heap[i].distance);
2606 }
2607#endif
2608
2609 // Pull matches out by increasing order of distance.
2610 // To avoid reassigning pointers that have already been matched, the loop keeps track
2611 // of which last and current pointers have been matched using the matchedXXXBits variables.
2612 // It also tracks the used pointer id bits.
2613 BitSet32 matchedLastBits(0);
2614 BitSet32 matchedCurrentBits(0);
2615 BitSet32 usedIdBits(0);
2616 bool first = true;
2617 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2618 for (;;) {
2619 if (first) {
2620 // The first time through the loop, we just consume the root element of
2621 // the heap (the one with smallest distance).
2622 first = false;
2623 } else {
2624 // Previous iterations consumed the root element of the heap.
2625 // Pop root element off of the heap (sift down).
2626 heapSize -= 1;
2627 assert(heapSize > 0);
2628
2629 // Sift down.
2630 heap[0] = heap[heapSize];
2631 for (uint32_t parentIndex = 0; ;) {
2632 uint32_t childIndex = parentIndex * 2 + 1;
2633 if (childIndex >= heapSize) {
2634 break;
2635 }
2636
2637 if (childIndex + 1 < heapSize
2638 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2639 childIndex += 1;
2640 }
2641
2642 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2643 break;
2644 }
2645
2646 swap(heap[parentIndex], heap[childIndex]);
2647 parentIndex = childIndex;
2648 }
2649
2650#if DEBUG_POINTER_ASSIGNMENT
2651 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2652 for (size_t i = 0; i < heapSize; i++) {
2653 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2654 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2655 heap[i].distance);
2656 }
2657#endif
2658 }
2659
2660 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2661 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2662
2663 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2664 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2665
2666 matchedCurrentBits.markBit(currentPointerIndex);
2667 matchedLastBits.markBit(lastPointerIndex);
2668
2669 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2670 mCurrentTouch.pointers[currentPointerIndex].id = id;
2671 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2672 usedIdBits.markBit(id);
2673
2674#if DEBUG_POINTER_ASSIGNMENT
2675 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2676 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2677#endif
2678 break;
2679 }
2680 }
2681
2682 // Assign fresh ids to new pointers.
2683 if (currentPointerCount > lastPointerCount) {
2684 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2685 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2686 uint32_t id = usedIdBits.firstUnmarkedBit();
2687
2688 mCurrentTouch.pointers[currentPointerIndex].id = id;
2689 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2690 usedIdBits.markBit(id);
2691
2692#if DEBUG_POINTER_ASSIGNMENT
2693 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2694 currentPointerIndex, id);
2695#endif
2696
2697 if (--i == 0) break; // done
2698 matchedCurrentBits.markBit(currentPointerIndex);
2699 }
2700 }
2701
2702 // Fix id bits.
2703 mCurrentTouch.idBits = usedIdBits;
2704 }
2705}
2706
2707/* Special hack for devices that have bad screen data: if one of the
2708 * points has moved more than a screen height from the last position,
2709 * then drop it. */
2710bool TouchInputMapper::applyBadTouchFilter() {
2711 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002712 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002713 return false;
2714 }
2715
2716 uint32_t pointerCount = mCurrentTouch.pointerCount;
2717
2718 // Nothing to do if there are no points.
2719 if (pointerCount == 0) {
2720 return false;
2721 }
2722
2723 // Don't do anything if a finger is going down or up. We run
2724 // here before assigning pointer IDs, so there isn't a good
2725 // way to do per-finger matching.
2726 if (pointerCount != mLastTouch.pointerCount) {
2727 return false;
2728 }
2729
2730 // We consider a single movement across more than a 7/16 of
2731 // the long size of the screen to be bad. This was a magic value
2732 // determined by looking at the maximum distance it is feasible
2733 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002734 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002735
2736 // XXX The original code in InputDevice.java included commented out
2737 // code for testing the X axis. Note that when we drop a point
2738 // we don't actually restore the old X either. Strange.
2739 // The old code also tries to track when bad points were previously
2740 // detected but it turns out that due to the placement of a "break"
2741 // at the end of the loop, we never set mDroppedBadPoint to true
2742 // so it is effectively dead code.
2743 // Need to figure out if the old code is busted or just overcomplicated
2744 // but working as intended.
2745
2746 // Look through all new points and see if any are farther than
2747 // acceptable from all previous points.
2748 for (uint32_t i = pointerCount; i-- > 0; ) {
2749 int32_t y = mCurrentTouch.pointers[i].y;
2750 int32_t closestY = INT_MAX;
2751 int32_t closestDeltaY = 0;
2752
2753#if DEBUG_HACKS
2754 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2755#endif
2756
2757 for (uint32_t j = pointerCount; j-- > 0; ) {
2758 int32_t lastY = mLastTouch.pointers[j].y;
2759 int32_t deltaY = abs(y - lastY);
2760
2761#if DEBUG_HACKS
2762 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2763 j, lastY, deltaY);
2764#endif
2765
2766 if (deltaY < maxDeltaY) {
2767 goto SkipSufficientlyClosePoint;
2768 }
2769 if (deltaY < closestDeltaY) {
2770 closestDeltaY = deltaY;
2771 closestY = lastY;
2772 }
2773 }
2774
2775 // Must not have found a close enough match.
2776#if DEBUG_HACKS
2777 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2778 i, y, closestY, closestDeltaY, maxDeltaY);
2779#endif
2780
2781 mCurrentTouch.pointers[i].y = closestY;
2782 return true; // XXX original code only corrects one point
2783
2784 SkipSufficientlyClosePoint: ;
2785 }
2786
2787 // No change.
2788 return false;
2789}
2790
2791/* Special hack for devices that have bad screen data: drop points where
2792 * the coordinate value for one axis has jumped to the other pointer's location.
2793 */
2794bool TouchInputMapper::applyJumpyTouchFilter() {
2795 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002796 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002797 return false;
2798 }
2799
2800 uint32_t pointerCount = mCurrentTouch.pointerCount;
2801 if (mLastTouch.pointerCount != pointerCount) {
2802#if DEBUG_HACKS
2803 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2804 mLastTouch.pointerCount, pointerCount);
2805 for (uint32_t i = 0; i < pointerCount; i++) {
2806 LOGD(" Pointer %d (%d, %d)", i,
2807 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2808 }
2809#endif
2810
2811 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2812 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2813 // Just drop the first few events going from 1 to 2 pointers.
2814 // They're bad often enough that they're not worth considering.
2815 mCurrentTouch.pointerCount = 1;
2816 mJumpyTouchFilter.jumpyPointsDropped += 1;
2817
2818#if DEBUG_HACKS
2819 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2820#endif
2821 return true;
2822 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2823 // The event when we go from 2 -> 1 tends to be messed up too
2824 mCurrentTouch.pointerCount = 2;
2825 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2826 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2827 mJumpyTouchFilter.jumpyPointsDropped += 1;
2828
2829#if DEBUG_HACKS
2830 for (int32_t i = 0; i < 2; i++) {
2831 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2832 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2833 }
2834#endif
2835 return true;
2836 }
2837 }
2838 // Reset jumpy points dropped on other transitions or if limit exceeded.
2839 mJumpyTouchFilter.jumpyPointsDropped = 0;
2840
2841#if DEBUG_HACKS
2842 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2843#endif
2844 return false;
2845 }
2846
2847 // We have the same number of pointers as last time.
2848 // A 'jumpy' point is one where the coordinate value for one axis
2849 // has jumped to the other pointer's location. No need to do anything
2850 // else if we only have one pointer.
2851 if (pointerCount < 2) {
2852 return false;
2853 }
2854
2855 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002856 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002857
2858 // We only replace the single worst jumpy point as characterized by pointer distance
2859 // in a single axis.
2860 int32_t badPointerIndex = -1;
2861 int32_t badPointerReplacementIndex = -1;
2862 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2863
2864 for (uint32_t i = pointerCount; i-- > 0; ) {
2865 int32_t x = mCurrentTouch.pointers[i].x;
2866 int32_t y = mCurrentTouch.pointers[i].y;
2867
2868#if DEBUG_HACKS
2869 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2870#endif
2871
2872 // Check if a touch point is too close to another's coordinates
2873 bool dropX = false, dropY = false;
2874 for (uint32_t j = 0; j < pointerCount; j++) {
2875 if (i == j) {
2876 continue;
2877 }
2878
2879 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2880 dropX = true;
2881 break;
2882 }
2883
2884 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2885 dropY = true;
2886 break;
2887 }
2888 }
2889 if (! dropX && ! dropY) {
2890 continue; // not jumpy
2891 }
2892
2893 // Find a replacement candidate by comparing with older points on the
2894 // complementary (non-jumpy) axis.
2895 int32_t distance = INT_MIN; // distance to be corrected
2896 int32_t replacementIndex = -1;
2897
2898 if (dropX) {
2899 // X looks too close. Find an older replacement point with a close Y.
2900 int32_t smallestDeltaY = INT_MAX;
2901 for (uint32_t j = 0; j < pointerCount; j++) {
2902 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2903 if (deltaY < smallestDeltaY) {
2904 smallestDeltaY = deltaY;
2905 replacementIndex = j;
2906 }
2907 }
2908 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2909 } else {
2910 // Y looks too close. Find an older replacement point with a close X.
2911 int32_t smallestDeltaX = INT_MAX;
2912 for (uint32_t j = 0; j < pointerCount; j++) {
2913 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2914 if (deltaX < smallestDeltaX) {
2915 smallestDeltaX = deltaX;
2916 replacementIndex = j;
2917 }
2918 }
2919 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2920 }
2921
2922 // If replacing this pointer would correct a worse error than the previous ones
2923 // considered, then use this replacement instead.
2924 if (distance > badPointerDistance) {
2925 badPointerIndex = i;
2926 badPointerReplacementIndex = replacementIndex;
2927 badPointerDistance = distance;
2928 }
2929 }
2930
2931 // Correct the jumpy pointer if one was found.
2932 if (badPointerIndex >= 0) {
2933#if DEBUG_HACKS
2934 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2935 badPointerIndex,
2936 mLastTouch.pointers[badPointerReplacementIndex].x,
2937 mLastTouch.pointers[badPointerReplacementIndex].y);
2938#endif
2939
2940 mCurrentTouch.pointers[badPointerIndex].x =
2941 mLastTouch.pointers[badPointerReplacementIndex].x;
2942 mCurrentTouch.pointers[badPointerIndex].y =
2943 mLastTouch.pointers[badPointerReplacementIndex].y;
2944 mJumpyTouchFilter.jumpyPointsDropped += 1;
2945 return true;
2946 }
2947 }
2948
2949 mJumpyTouchFilter.jumpyPointsDropped = 0;
2950 return false;
2951}
2952
2953/* Special hack for devices that have bad screen data: aggregate and
2954 * compute averages of the coordinate data, to reduce the amount of
2955 * jitter seen by applications. */
2956void TouchInputMapper::applyAveragingTouchFilter() {
2957 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2958 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2959 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2960 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002961 int32_t pressure;
2962 switch (mCalibration.pressureSource) {
2963 case Calibration::PRESSURE_SOURCE_PRESSURE:
2964 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2965 break;
2966 case Calibration::PRESSURE_SOURCE_TOUCH:
2967 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2968 break;
2969 default:
2970 pressure = 1;
2971 break;
2972 }
Jeff Browne57e8952010-07-23 21:28:06 -07002973
2974 if (mLastTouch.idBits.hasBit(id)) {
2975 // Pointer was down before and is still down now.
2976 // Compute average over history trace.
2977 uint32_t start = mAveragingTouchFilter.historyStart[id];
2978 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2979
2980 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2981 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2982 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2983
2984#if DEBUG_HACKS
2985 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2986 id, distance);
2987#endif
2988
2989 if (distance < AVERAGING_DISTANCE_LIMIT) {
2990 // Increment end index in preparation for recording new historical data.
2991 end += 1;
2992 if (end > AVERAGING_HISTORY_SIZE) {
2993 end = 0;
2994 }
2995
2996 // If the end index has looped back to the start index then we have filled
2997 // the historical trace up to the desired size so we drop the historical
2998 // data at the start of the trace.
2999 if (end == start) {
3000 start += 1;
3001 if (start > AVERAGING_HISTORY_SIZE) {
3002 start = 0;
3003 }
3004 }
3005
3006 // Add the raw data to the historical trace.
3007 mAveragingTouchFilter.historyStart[id] = start;
3008 mAveragingTouchFilter.historyEnd[id] = end;
3009 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3010 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3011 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3012
3013 // Average over all historical positions in the trace by total pressure.
3014 int32_t averagedX = 0;
3015 int32_t averagedY = 0;
3016 int32_t totalPressure = 0;
3017 for (;;) {
3018 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3019 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3020 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3021 .pointers[id].pressure;
3022
3023 averagedX += historicalX * historicalPressure;
3024 averagedY += historicalY * historicalPressure;
3025 totalPressure += historicalPressure;
3026
3027 if (start == end) {
3028 break;
3029 }
3030
3031 start += 1;
3032 if (start > AVERAGING_HISTORY_SIZE) {
3033 start = 0;
3034 }
3035 }
3036
Jeff Brown38a7fab2010-08-30 03:02:23 -07003037 if (totalPressure != 0) {
3038 averagedX /= totalPressure;
3039 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07003040
3041#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07003042 LOGD("AveragingTouchFilter: Pointer id %d - "
3043 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3044 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07003045#endif
3046
Jeff Brown38a7fab2010-08-30 03:02:23 -07003047 mCurrentTouch.pointers[currentIndex].x = averagedX;
3048 mCurrentTouch.pointers[currentIndex].y = averagedY;
3049 }
Jeff Browne57e8952010-07-23 21:28:06 -07003050 } else {
3051#if DEBUG_HACKS
3052 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3053#endif
3054 }
3055 } else {
3056#if DEBUG_HACKS
3057 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3058#endif
3059 }
3060
3061 // Reset pointer history.
3062 mAveragingTouchFilter.historyStart[id] = 0;
3063 mAveragingTouchFilter.historyEnd[id] = 0;
3064 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3065 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3066 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3067 }
3068}
3069
3070int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003071 { // acquire lock
3072 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003073
Jeff Brownb51719b2010-07-29 18:18:33 -07003074 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003075 return AKEY_STATE_VIRTUAL;
3076 }
3077
Jeff Brownb51719b2010-07-29 18:18:33 -07003078 size_t numVirtualKeys = mLocked.virtualKeys.size();
3079 for (size_t i = 0; i < numVirtualKeys; i++) {
3080 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003081 if (virtualKey.keyCode == keyCode) {
3082 return AKEY_STATE_UP;
3083 }
3084 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003085 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003086
3087 return AKEY_STATE_UNKNOWN;
3088}
3089
3090int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003091 { // acquire lock
3092 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003093
Jeff Brownb51719b2010-07-29 18:18:33 -07003094 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003095 return AKEY_STATE_VIRTUAL;
3096 }
3097
Jeff Brownb51719b2010-07-29 18:18:33 -07003098 size_t numVirtualKeys = mLocked.virtualKeys.size();
3099 for (size_t i = 0; i < numVirtualKeys; i++) {
3100 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003101 if (virtualKey.scanCode == scanCode) {
3102 return AKEY_STATE_UP;
3103 }
3104 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003105 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003106
3107 return AKEY_STATE_UNKNOWN;
3108}
3109
3110bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3111 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003112 { // acquire lock
3113 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003114
Jeff Brownb51719b2010-07-29 18:18:33 -07003115 size_t numVirtualKeys = mLocked.virtualKeys.size();
3116 for (size_t i = 0; i < numVirtualKeys; i++) {
3117 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003118
3119 for (size_t i = 0; i < numCodes; i++) {
3120 if (virtualKey.keyCode == keyCodes[i]) {
3121 outFlags[i] = 1;
3122 }
3123 }
3124 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003125 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003126
3127 return true;
3128}
3129
3130
3131// --- SingleTouchInputMapper ---
3132
3133SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3134 TouchInputMapper(device, associatedDisplayId) {
3135 initialize();
3136}
3137
3138SingleTouchInputMapper::~SingleTouchInputMapper() {
3139}
3140
3141void SingleTouchInputMapper::initialize() {
3142 mAccumulator.clear();
3143
3144 mDown = false;
3145 mX = 0;
3146 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003147 mPressure = 0; // default to 0 for devices that don't report pressure
3148 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003149}
3150
3151void SingleTouchInputMapper::reset() {
3152 TouchInputMapper::reset();
3153
Jeff Browne57e8952010-07-23 21:28:06 -07003154 initialize();
3155 }
3156
3157void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3158 switch (rawEvent->type) {
3159 case EV_KEY:
3160 switch (rawEvent->scanCode) {
3161 case BTN_TOUCH:
3162 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3163 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003164 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3165 // not have received valid position information yet. This logic assumes that
3166 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003167 break;
3168 }
3169 break;
3170
3171 case EV_ABS:
3172 switch (rawEvent->scanCode) {
3173 case ABS_X:
3174 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3175 mAccumulator.absX = rawEvent->value;
3176 break;
3177 case ABS_Y:
3178 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3179 mAccumulator.absY = rawEvent->value;
3180 break;
3181 case ABS_PRESSURE:
3182 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3183 mAccumulator.absPressure = rawEvent->value;
3184 break;
3185 case ABS_TOOL_WIDTH:
3186 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3187 mAccumulator.absToolWidth = rawEvent->value;
3188 break;
3189 }
3190 break;
3191
3192 case EV_SYN:
3193 switch (rawEvent->scanCode) {
3194 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003195 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003196 break;
3197 }
3198 break;
3199 }
3200}
3201
3202void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003203 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003204 if (fields == 0) {
3205 return; // no new state changes, so nothing to do
3206 }
Jeff Browne57e8952010-07-23 21:28:06 -07003207
3208 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3209 mDown = mAccumulator.btnTouch;
3210 }
3211
3212 if (fields & Accumulator::FIELD_ABS_X) {
3213 mX = mAccumulator.absX;
3214 }
3215
3216 if (fields & Accumulator::FIELD_ABS_Y) {
3217 mY = mAccumulator.absY;
3218 }
3219
3220 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3221 mPressure = mAccumulator.absPressure;
3222 }
3223
3224 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003225 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003226 }
3227
3228 mCurrentTouch.clear();
3229
3230 if (mDown) {
3231 mCurrentTouch.pointerCount = 1;
3232 mCurrentTouch.pointers[0].id = 0;
3233 mCurrentTouch.pointers[0].x = mX;
3234 mCurrentTouch.pointers[0].y = mY;
3235 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003236 mCurrentTouch.pointers[0].touchMajor = 0;
3237 mCurrentTouch.pointers[0].touchMinor = 0;
3238 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3239 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003240 mCurrentTouch.pointers[0].orientation = 0;
3241 mCurrentTouch.idToIndex[0] = 0;
3242 mCurrentTouch.idBits.markBit(0);
3243 }
3244
3245 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003246
3247 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003248}
3249
Jeff Brown38a7fab2010-08-30 03:02:23 -07003250void SingleTouchInputMapper::configureRawAxes() {
3251 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003252
Jeff Brown38a7fab2010-08-30 03:02:23 -07003253 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3254 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3255 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3256 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003257}
3258
3259
3260// --- MultiTouchInputMapper ---
3261
3262MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3263 TouchInputMapper(device, associatedDisplayId) {
3264 initialize();
3265}
3266
3267MultiTouchInputMapper::~MultiTouchInputMapper() {
3268}
3269
3270void MultiTouchInputMapper::initialize() {
3271 mAccumulator.clear();
3272}
3273
3274void MultiTouchInputMapper::reset() {
3275 TouchInputMapper::reset();
3276
Jeff Browne57e8952010-07-23 21:28:06 -07003277 initialize();
3278}
3279
3280void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3281 switch (rawEvent->type) {
3282 case EV_ABS: {
3283 uint32_t pointerIndex = mAccumulator.pointerCount;
3284 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3285
3286 switch (rawEvent->scanCode) {
3287 case ABS_MT_POSITION_X:
3288 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3289 pointer->absMTPositionX = rawEvent->value;
3290 break;
3291 case ABS_MT_POSITION_Y:
3292 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3293 pointer->absMTPositionY = rawEvent->value;
3294 break;
3295 case ABS_MT_TOUCH_MAJOR:
3296 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3297 pointer->absMTTouchMajor = rawEvent->value;
3298 break;
3299 case ABS_MT_TOUCH_MINOR:
3300 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3301 pointer->absMTTouchMinor = rawEvent->value;
3302 break;
3303 case ABS_MT_WIDTH_MAJOR:
3304 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3305 pointer->absMTWidthMajor = rawEvent->value;
3306 break;
3307 case ABS_MT_WIDTH_MINOR:
3308 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3309 pointer->absMTWidthMinor = rawEvent->value;
3310 break;
3311 case ABS_MT_ORIENTATION:
3312 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3313 pointer->absMTOrientation = rawEvent->value;
3314 break;
3315 case ABS_MT_TRACKING_ID:
3316 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3317 pointer->absMTTrackingId = rawEvent->value;
3318 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003319 case ABS_MT_PRESSURE:
3320 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3321 pointer->absMTPressure = rawEvent->value;
3322 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003323 }
3324 break;
3325 }
3326
3327 case EV_SYN:
3328 switch (rawEvent->scanCode) {
3329 case SYN_MT_REPORT: {
3330 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3331 uint32_t pointerIndex = mAccumulator.pointerCount;
3332
3333 if (mAccumulator.pointers[pointerIndex].fields) {
3334 if (pointerIndex == MAX_POINTERS) {
3335 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3336 MAX_POINTERS);
3337 } else {
3338 pointerIndex += 1;
3339 mAccumulator.pointerCount = pointerIndex;
3340 }
3341 }
3342
3343 mAccumulator.pointers[pointerIndex].clear();
3344 break;
3345 }
3346
3347 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003348 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003349 break;
3350 }
3351 break;
3352 }
3353}
3354
3355void MultiTouchInputMapper::sync(nsecs_t when) {
3356 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003357 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003358
Jeff Browne57e8952010-07-23 21:28:06 -07003359 uint32_t inCount = mAccumulator.pointerCount;
3360 uint32_t outCount = 0;
3361 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003362
Jeff Browne57e8952010-07-23 21:28:06 -07003363 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003364
Jeff Browne57e8952010-07-23 21:28:06 -07003365 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003366 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3367 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003368
Jeff Browne57e8952010-07-23 21:28:06 -07003369 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003370 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3371 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003372 continue;
3373 }
3374
Jeff Brownd64c8552010-08-17 20:38:35 -07003375 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3376 outPointer.x = inPointer.absMTPositionX;
3377 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003378
Jeff Brown38a7fab2010-08-30 03:02:23 -07003379 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3380 if (inPointer.absMTPressure <= 0) {
Jeff Brown3c3cc622010-10-20 15:33:38 -07003381 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3382 // a pointer going up. Drop this finger.
Jeff Brownd64c8552010-08-17 20:38:35 -07003383 continue;
3384 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003385 outPointer.pressure = inPointer.absMTPressure;
3386 } else {
3387 // Default pressure to 0 if absent.
3388 outPointer.pressure = 0;
3389 }
3390
3391 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3392 if (inPointer.absMTTouchMajor <= 0) {
3393 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3394 // a pointer going up. Drop this finger.
3395 continue;
3396 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003397 outPointer.touchMajor = inPointer.absMTTouchMajor;
3398 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003399 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003400 outPointer.touchMajor = 0;
3401 }
Jeff Browne839a582010-04-22 18:58:52 -07003402
Jeff Brownd64c8552010-08-17 20:38:35 -07003403 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3404 outPointer.touchMinor = inPointer.absMTTouchMinor;
3405 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003406 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003407 outPointer.touchMinor = outPointer.touchMajor;
3408 }
Jeff Browne839a582010-04-22 18:58:52 -07003409
Jeff Brownd64c8552010-08-17 20:38:35 -07003410 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3411 outPointer.toolMajor = inPointer.absMTWidthMajor;
3412 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003413 // Default tool area to 0 if absent.
3414 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003415 }
Jeff Browne839a582010-04-22 18:58:52 -07003416
Jeff Brownd64c8552010-08-17 20:38:35 -07003417 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3418 outPointer.toolMinor = inPointer.absMTWidthMinor;
3419 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003420 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003421 outPointer.toolMinor = outPointer.toolMajor;
3422 }
3423
3424 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3425 outPointer.orientation = inPointer.absMTOrientation;
3426 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003427 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003428 outPointer.orientation = 0;
3429 }
3430
Jeff Brown38a7fab2010-08-30 03:02:23 -07003431 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003432 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003433 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3434 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003435
Jeff Browne57e8952010-07-23 21:28:06 -07003436 if (id > MAX_POINTER_ID) {
3437#if DEBUG_POINTERS
3438 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003439 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003440 id, MAX_POINTER_ID);
3441#endif
3442 havePointerIds = false;
3443 }
3444 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003445 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003446 mCurrentTouch.idToIndex[id] = outCount;
3447 mCurrentTouch.idBits.markBit(id);
3448 }
3449 } else {
3450 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003451 }
3452 }
Jeff Browne839a582010-04-22 18:58:52 -07003453
Jeff Browne57e8952010-07-23 21:28:06 -07003454 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003455 }
3456
Jeff Browne57e8952010-07-23 21:28:06 -07003457 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003458
Jeff Browne57e8952010-07-23 21:28:06 -07003459 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003460
3461 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003462}
3463
Jeff Brown38a7fab2010-08-30 03:02:23 -07003464void MultiTouchInputMapper::configureRawAxes() {
3465 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003466
Jeff Brown38a7fab2010-08-30 03:02:23 -07003467 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3468 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3469 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3470 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3471 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3472 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3473 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3474 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003475}
3476
Jeff Browne839a582010-04-22 18:58:52 -07003477
3478} // namespace android