blob: d57b38c2e2f72b6378a7e86d57dee993a1945e46 [file] [log] [blame]
Jeff Brown46b9ac02010-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 Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070021
Jeff Brown5c225b12010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Brown46b9ac02010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070029#include <stdlib.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070030#include <unistd.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070031#include <errno.h>
32#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070033#include <math.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070034
Jeff Brown8d608662010-08-30 03:02:23 -070035#define INDENT " "
36
Jeff Brown46b9ac02010-04-22 18:58:52 -070037namespace android {
38
39// --- Static Functions ---
40
41template<typename T>
42inline static T abs(const T& value) {
43 return value < 0 ? - value : value;
44}
45
46template<typename T>
47inline static T min(const T& a, const T& b) {
48 return a < b ? a : b;
49}
50
Jeff Brown5c225b12010-06-16 01:53:36 -070051template<typename T>
52inline static void swap(T& a, T& b) {
53 T temp = a;
54 a = b;
55 b = temp;
56}
57
Jeff Brown8d608662010-08-30 03:02:23 -070058inline static float avg(float x, float y) {
59 return (x + y) / 2;
60}
61
62inline static float pythag(float x, float y) {
63 return sqrtf(x * x + y * y);
64}
65
Jeff Brown5c225b12010-06-16 01:53:36 -070066
Jeff Brown46b9ac02010-04-22 18:58:52 -070067int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
68 int32_t mask;
69 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -070070 case AKEYCODE_ALT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070071 mask = AMETA_ALT_LEFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070072 break;
Jeff Brownfd035822010-06-30 16:10:35 -070073 case AKEYCODE_ALT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070074 mask = AMETA_ALT_RIGHT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070075 break;
Jeff Brownfd035822010-06-30 16:10:35 -070076 case AKEYCODE_SHIFT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070077 mask = AMETA_SHIFT_LEFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070078 break;
Jeff Brownfd035822010-06-30 16:10:35 -070079 case AKEYCODE_SHIFT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070080 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070081 break;
Jeff Brownfd035822010-06-30 16:10:35 -070082 case AKEYCODE_SYM:
Jeff Brownc5ed5912010-07-14 18:48:53 -070083 mask = AMETA_SYM_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070084 break;
85 default:
86 return oldMetaState;
87 }
88
89 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brownc5ed5912010-07-14 18:48:53 -070090 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Brown46b9ac02010-04-22 18:58:52 -070091
Jeff Brownc5ed5912010-07-14 18:48:53 -070092 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
93 newMetaState |= AMETA_ALT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070094 }
95
Jeff Brownc5ed5912010-07-14 18:48:53 -070096 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
97 newMetaState |= AMETA_SHIFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070098 }
99
100 return newMetaState;
101}
102
103static const int32_t keyCodeRotationMap[][4] = {
104 // key codes enumerated counter-clockwise with the original (unrotated) key first
105 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -0700106 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
107 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
108 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
109 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac02010-04-22 18:58:52 -0700110};
111static const int keyCodeRotationMapSize =
112 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
113
114int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700115 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700116 for (int i = 0; i < keyCodeRotationMapSize; i++) {
117 if (keyCode == keyCodeRotationMap[i][0]) {
118 return keyCodeRotationMap[i][orientation];
119 }
120 }
121 }
122 return keyCode;
123}
124
Jeff Brown6d0fec22010-07-23 21:28:06 -0700125static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
126 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
127}
128
Jeff Brown46b9ac02010-04-22 18:58:52 -0700129
Jeff Brown8d608662010-08-30 03:02:23 -0700130// --- InputDeviceCalibration ---
131
132InputDeviceCalibration::InputDeviceCalibration() {
133}
134
135void InputDeviceCalibration::clear() {
136 mProperties.clear();
137}
138
139void InputDeviceCalibration::addProperty(const String8& key, const String8& value) {
140 mProperties.add(key, value);
141}
142
143bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const {
144 ssize_t index = mProperties.indexOfKey(key);
145 if (index < 0) {
146 return false;
147 }
148
149 outValue = mProperties.valueAt(index);
150 return true;
151}
152
153bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const {
154 String8 stringValue;
155 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
156 return false;
157 }
158
159 char* end;
160 int value = strtol(stringValue.string(), & end, 10);
161 if (*end != '\0') {
162 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.",
163 key.string(), stringValue.string());
164 return false;
165 }
166 outValue = value;
167 return true;
168}
169
170bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const {
171 String8 stringValue;
172 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
173 return false;
174 }
175
176 char* end;
177 float value = strtof(stringValue.string(), & end);
178 if (*end != '\0') {
179 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.",
180 key.string(), stringValue.string());
181 return false;
182 }
183 outValue = value;
184 return true;
185}
186
187
Jeff Brown46b9ac02010-04-22 18:58:52 -0700188// --- InputReader ---
189
190InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700191 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700192 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700193 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
194 mGlobalMetaState(0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700195 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700196 updateGlobalMetaState();
197 updateInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700198}
199
200InputReader::~InputReader() {
201 for (size_t i = 0; i < mDevices.size(); i++) {
202 delete mDevices.valueAt(i);
203 }
204}
205
206void InputReader::loopOnce() {
207 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700208 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700209
210#if DEBUG_RAW_EVENTS
211 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
212 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
213 rawEvent.value);
214#endif
215
216 process(& rawEvent);
217}
218
219void InputReader::process(const RawEvent* rawEvent) {
220 switch (rawEvent->type) {
221 case EventHubInterface::DEVICE_ADDED:
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 addDevice(rawEvent->when, rawEvent->deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700223 break;
224
225 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown6d0fec22010-07-23 21:28:06 -0700226 removeDevice(rawEvent->when, rawEvent->deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700227 break;
228
Jeff Brown6d0fec22010-07-23 21:28:06 -0700229 default:
230 consumeEvent(rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700231 break;
232 }
233}
234
Jeff Brown6d0fec22010-07-23 21:28:06 -0700235void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
236 String8 name = mEventHub->getDeviceName(deviceId);
237 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
238
Jeff Brown8d608662010-08-30 03:02:23 -0700239 // Write a log message about the added device as a heading for subsequent log messages.
240 LOGI("Device added: id=0x%x, name=%s", deviceId, name.string());
241
Jeff Brown6d0fec22010-07-23 21:28:06 -0700242 InputDevice* device = createDevice(deviceId, name, classes);
243 device->configure();
244
Jeff Brown8d608662010-08-30 03:02:23 -0700245 if (device->isIgnored()) {
246 LOGI(INDENT "Sources: none (device is ignored)");
247 } else {
248 LOGI(INDENT "Sources: 0x%08x", device->getSources());
249 }
250
Jeff Brown6d0fec22010-07-23 21:28:06 -0700251 bool added = false;
252 { // acquire device registry writer lock
253 RWLock::AutoWLock _wl(mDeviceRegistryLock);
254
255 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
256 if (deviceIndex < 0) {
257 mDevices.add(deviceId, device);
258 added = true;
259 }
260 } // release device registry writer lock
261
262 if (! added) {
263 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
264 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700265 return;
266 }
267
Jeff Brown6d0fec22010-07-23 21:28:06 -0700268 handleConfigurationChanged(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700269}
270
Jeff Brown6d0fec22010-07-23 21:28:06 -0700271void InputReader::removeDevice(nsecs_t when, int32_t deviceId) {
272 bool removed = false;
273 InputDevice* device = NULL;
274 { // acquire device registry writer lock
275 RWLock::AutoWLock _wl(mDeviceRegistryLock);
276
277 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
278 if (deviceIndex >= 0) {
279 device = mDevices.valueAt(deviceIndex);
280 mDevices.removeItemsAt(deviceIndex, 1);
281 removed = true;
282 }
283 } // release device registry writer lock
284
285 if (! removed) {
286 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700287 return;
288 }
289
Jeff Brown8d608662010-08-30 03:02:23 -0700290 // Write a log message about the removed device as a heading for subsequent log messages.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700291 if (device->isIgnored()) {
292 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
293 device->getId(), device->getName().string());
294 } else {
295 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
296 device->getId(), device->getName().string(), device->getSources());
297 }
298
Jeff Brown8d608662010-08-30 03:02:23 -0700299 device->reset();
300
Jeff Brown6d0fec22010-07-23 21:28:06 -0700301 delete device;
302
303 handleConfigurationChanged(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700304}
305
Jeff Brown6d0fec22010-07-23 21:28:06 -0700306InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
307 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700308
Jeff Brown6d0fec22010-07-23 21:28:06 -0700309 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Brown46b9ac02010-04-22 18:58:52 -0700310
Jeff Brown6d0fec22010-07-23 21:28:06 -0700311 // Switch-like devices.
312 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
313 device->addMapper(new SwitchInputMapper(device));
314 }
315
316 // Keyboard-like devices.
317 uint32_t keyboardSources = 0;
318 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
319 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
320 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
321 }
322 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
323 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
324 }
325 if (classes & INPUT_DEVICE_CLASS_DPAD) {
326 keyboardSources |= AINPUT_SOURCE_DPAD;
327 }
328 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
329 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
330 }
331
332 if (keyboardSources != 0) {
333 device->addMapper(new KeyboardInputMapper(device,
334 associatedDisplayId, keyboardSources, keyboardType));
335 }
336
337 // Trackball-like devices.
338 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
339 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
340 }
341
342 // Touchscreen-like devices.
343 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
344 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
345 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
346 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
347 }
348
349 return device;
350}
351
352void InputReader::consumeEvent(const RawEvent* rawEvent) {
353 int32_t deviceId = rawEvent->deviceId;
354
355 { // acquire device registry reader lock
356 RWLock::AutoRLock _rl(mDeviceRegistryLock);
357
358 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
359 if (deviceIndex < 0) {
360 LOGW("Discarding event for unknown deviceId %d.", deviceId);
361 return;
362 }
363
364 InputDevice* device = mDevices.valueAt(deviceIndex);
365 if (device->isIgnored()) {
366 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
367 return;
368 }
369
370 device->process(rawEvent);
371 } // release device registry reader lock
372}
373
374void InputReader::handleConfigurationChanged(nsecs_t when) {
375 // Reset global meta state because it depends on the list of all configured devices.
376 updateGlobalMetaState();
377
378 // Update input configuration.
379 updateInputConfiguration();
380
381 // Enqueue configuration changed.
382 mDispatcher->notifyConfigurationChanged(when);
383}
384
385void InputReader::configureExcludedDevices() {
386 Vector<String8> excludedDeviceNames;
387 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
388
389 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
390 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
391 }
392}
393
394void InputReader::updateGlobalMetaState() {
395 { // acquire state lock
396 AutoMutex _l(mStateLock);
397
398 mGlobalMetaState = 0;
399
400 { // acquire device registry reader lock
401 RWLock::AutoRLock _rl(mDeviceRegistryLock);
402
403 for (size_t i = 0; i < mDevices.size(); i++) {
404 InputDevice* device = mDevices.valueAt(i);
405 mGlobalMetaState |= device->getMetaState();
406 }
407 } // release device registry reader lock
408 } // release state lock
409}
410
411int32_t InputReader::getGlobalMetaState() {
412 { // acquire state lock
413 AutoMutex _l(mStateLock);
414
415 return mGlobalMetaState;
416 } // release state lock
417}
418
419void InputReader::updateInputConfiguration() {
420 { // acquire state lock
421 AutoMutex _l(mStateLock);
422
423 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
424 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
425 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
426 { // acquire device registry reader lock
427 RWLock::AutoRLock _rl(mDeviceRegistryLock);
428
429 InputDeviceInfo deviceInfo;
430 for (size_t i = 0; i < mDevices.size(); i++) {
431 InputDevice* device = mDevices.valueAt(i);
432 device->getDeviceInfo(& deviceInfo);
433 uint32_t sources = deviceInfo.getSources();
434
435 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
436 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
437 }
438 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
439 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
440 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
441 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
442 }
443 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
444 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700445 }
446 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700447 } // release device registry reader lock
Jeff Brown46b9ac02010-04-22 18:58:52 -0700448
Jeff Brown6d0fec22010-07-23 21:28:06 -0700449 mInputConfiguration.touchScreen = touchScreenConfig;
450 mInputConfiguration.keyboard = keyboardConfig;
451 mInputConfiguration.navigation = navigationConfig;
452 } // release state lock
453}
454
455void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
456 { // acquire state lock
457 AutoMutex _l(mStateLock);
458
459 *outConfiguration = mInputConfiguration;
460 } // release state lock
461}
462
463status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
464 { // acquire device registry reader lock
465 RWLock::AutoRLock _rl(mDeviceRegistryLock);
466
467 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
468 if (deviceIndex < 0) {
469 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700470 }
471
Jeff Brown6d0fec22010-07-23 21:28:06 -0700472 InputDevice* device = mDevices.valueAt(deviceIndex);
473 if (device->isIgnored()) {
474 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700475 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700476
477 device->getDeviceInfo(outDeviceInfo);
478 return OK;
479 } // release device registy reader lock
480}
481
482void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
483 outDeviceIds.clear();
484
485 { // acquire device registry reader lock
486 RWLock::AutoRLock _rl(mDeviceRegistryLock);
487
488 size_t numDevices = mDevices.size();
489 for (size_t i = 0; i < numDevices; i++) {
490 InputDevice* device = mDevices.valueAt(i);
491 if (! device->isIgnored()) {
492 outDeviceIds.add(device->getId());
493 }
494 }
495 } // release device registy reader lock
496}
497
498int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
499 int32_t keyCode) {
500 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
501}
502
503int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
504 int32_t scanCode) {
505 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
506}
507
508int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
509 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
510}
511
512int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
513 GetStateFunc getStateFunc) {
514 { // acquire device registry reader lock
515 RWLock::AutoRLock _rl(mDeviceRegistryLock);
516
517 int32_t result = AKEY_STATE_UNKNOWN;
518 if (deviceId >= 0) {
519 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
520 if (deviceIndex >= 0) {
521 InputDevice* device = mDevices.valueAt(deviceIndex);
522 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
523 result = (device->*getStateFunc)(sourceMask, code);
524 }
525 }
526 } else {
527 size_t numDevices = mDevices.size();
528 for (size_t i = 0; i < numDevices; i++) {
529 InputDevice* device = mDevices.valueAt(i);
530 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
531 result = (device->*getStateFunc)(sourceMask, code);
532 if (result >= AKEY_STATE_DOWN) {
533 return result;
534 }
535 }
536 }
537 }
538 return result;
539 } // release device registy reader lock
540}
541
542bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
543 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
544 memset(outFlags, 0, numCodes);
545 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
546}
547
548bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
549 const int32_t* keyCodes, uint8_t* outFlags) {
550 { // acquire device registry reader lock
551 RWLock::AutoRLock _rl(mDeviceRegistryLock);
552 bool result = false;
553 if (deviceId >= 0) {
554 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
555 if (deviceIndex >= 0) {
556 InputDevice* device = mDevices.valueAt(deviceIndex);
557 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
558 result = device->markSupportedKeyCodes(sourceMask,
559 numCodes, keyCodes, outFlags);
560 }
561 }
562 } else {
563 size_t numDevices = mDevices.size();
564 for (size_t i = 0; i < numDevices; i++) {
565 InputDevice* device = mDevices.valueAt(i);
566 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
567 result |= device->markSupportedKeyCodes(sourceMask,
568 numCodes, keyCodes, outFlags);
569 }
570 }
571 }
572 return result;
573 } // release device registy reader lock
574}
575
576
577// --- InputReaderThread ---
578
579InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
580 Thread(/*canCallJava*/ true), mReader(reader) {
581}
582
583InputReaderThread::~InputReaderThread() {
584}
585
586bool InputReaderThread::threadLoop() {
587 mReader->loopOnce();
588 return true;
589}
590
591
592// --- InputDevice ---
593
594InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
595 mContext(context), mId(id), mName(name), mSources(0) {
596}
597
598InputDevice::~InputDevice() {
599 size_t numMappers = mMappers.size();
600 for (size_t i = 0; i < numMappers; i++) {
601 delete mMappers[i];
602 }
603 mMappers.clear();
604}
605
606void InputDevice::addMapper(InputMapper* mapper) {
607 mMappers.add(mapper);
608}
609
610void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700611 if (! isIgnored()) {
612 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
613 }
614
Jeff Brown6d0fec22010-07-23 21:28:06 -0700615 mSources = 0;
616
617 size_t numMappers = mMappers.size();
618 for (size_t i = 0; i < numMappers; i++) {
619 InputMapper* mapper = mMappers[i];
620 mapper->configure();
621 mSources |= mapper->getSources();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700622 }
623}
624
Jeff Brown6d0fec22010-07-23 21:28:06 -0700625void InputDevice::reset() {
626 size_t numMappers = mMappers.size();
627 for (size_t i = 0; i < numMappers; i++) {
628 InputMapper* mapper = mMappers[i];
629 mapper->reset();
630 }
631}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700632
Jeff Brown6d0fec22010-07-23 21:28:06 -0700633void InputDevice::process(const RawEvent* rawEvent) {
634 size_t numMappers = mMappers.size();
635 for (size_t i = 0; i < numMappers; i++) {
636 InputMapper* mapper = mMappers[i];
637 mapper->process(rawEvent);
638 }
639}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700640
Jeff Brown6d0fec22010-07-23 21:28:06 -0700641void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
642 outDeviceInfo->initialize(mId, mName);
643
644 size_t numMappers = mMappers.size();
645 for (size_t i = 0; i < numMappers; i++) {
646 InputMapper* mapper = mMappers[i];
647 mapper->populateDeviceInfo(outDeviceInfo);
648 }
649}
650
651int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
652 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
653}
654
655int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
656 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
657}
658
659int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
660 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
661}
662
663int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
664 int32_t result = AKEY_STATE_UNKNOWN;
665 size_t numMappers = mMappers.size();
666 for (size_t i = 0; i < numMappers; i++) {
667 InputMapper* mapper = mMappers[i];
668 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
669 result = (mapper->*getStateFunc)(sourceMask, code);
670 if (result >= AKEY_STATE_DOWN) {
671 return result;
672 }
673 }
674 }
675 return result;
676}
677
678bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
679 const int32_t* keyCodes, uint8_t* outFlags) {
680 bool result = false;
681 size_t numMappers = mMappers.size();
682 for (size_t i = 0; i < numMappers; i++) {
683 InputMapper* mapper = mMappers[i];
684 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
685 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
686 }
687 }
688 return result;
689}
690
691int32_t InputDevice::getMetaState() {
692 int32_t result = 0;
693 size_t numMappers = mMappers.size();
694 for (size_t i = 0; i < numMappers; i++) {
695 InputMapper* mapper = mMappers[i];
696 result |= mapper->getMetaState();
697 }
698 return result;
699}
700
701
702// --- InputMapper ---
703
704InputMapper::InputMapper(InputDevice* device) :
705 mDevice(device), mContext(device->getContext()) {
706}
707
708InputMapper::~InputMapper() {
709}
710
711void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
712 info->addSource(getSources());
713}
714
715void InputMapper::configure() {
716}
717
718void InputMapper::reset() {
719}
720
721int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
722 return AKEY_STATE_UNKNOWN;
723}
724
725int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
726 return AKEY_STATE_UNKNOWN;
727}
728
729int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
730 return AKEY_STATE_UNKNOWN;
731}
732
733bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
734 const int32_t* keyCodes, uint8_t* outFlags) {
735 return false;
736}
737
738int32_t InputMapper::getMetaState() {
739 return 0;
740}
741
742bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
743 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
744 getDispatcher()->notifyAppSwitchComing(when);
745 }
746
747 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
748}
749
750
751// --- SwitchInputMapper ---
752
753SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
754 InputMapper(device) {
755}
756
757SwitchInputMapper::~SwitchInputMapper() {
758}
759
760uint32_t SwitchInputMapper::getSources() {
761 return 0;
762}
763
764void SwitchInputMapper::process(const RawEvent* rawEvent) {
765 switch (rawEvent->type) {
766 case EV_SW:
767 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
768 break;
769 }
770}
771
772void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
773 uint32_t policyFlags = 0;
774 int32_t policyActions = getPolicy()->interceptSwitch(
775 when, switchCode, switchValue, policyFlags);
776
777 applyStandardPolicyActions(when, policyActions);
778}
779
780int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
781 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
782}
783
784
785// --- KeyboardInputMapper ---
786
787KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
788 uint32_t sources, int32_t keyboardType) :
789 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
790 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700791 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700792}
793
794KeyboardInputMapper::~KeyboardInputMapper() {
795}
796
Jeff Brown6328cdc2010-07-29 18:18:33 -0700797void KeyboardInputMapper::initializeLocked() {
798 mLocked.metaState = AMETA_NONE;
799 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700800}
801
802uint32_t KeyboardInputMapper::getSources() {
803 return mSources;
804}
805
806void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
807 InputMapper::populateDeviceInfo(info);
808
809 info->setKeyboardType(mKeyboardType);
810}
811
812void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700813 for (;;) {
814 int32_t keyCode, scanCode;
815 { // acquire lock
816 AutoMutex _l(mLock);
817
818 // Synthesize key up event on reset if keys are currently down.
819 if (mLocked.keyDowns.isEmpty()) {
820 initializeLocked();
821 break; // done
822 }
823
824 const KeyDown& keyDown = mLocked.keyDowns.top();
825 keyCode = keyDown.keyCode;
826 scanCode = keyDown.scanCode;
827 } // release lock
828
Jeff Brown6d0fec22010-07-23 21:28:06 -0700829 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700830 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700831 }
832
833 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700834 getContext()->updateGlobalMetaState();
835}
836
837void KeyboardInputMapper::process(const RawEvent* rawEvent) {
838 switch (rawEvent->type) {
839 case EV_KEY: {
840 int32_t scanCode = rawEvent->scanCode;
841 if (isKeyboardOrGamepadKey(scanCode)) {
842 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
843 rawEvent->flags);
844 }
845 break;
846 }
847 }
848}
849
850bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
851 return scanCode < BTN_MOUSE
852 || scanCode >= KEY_OK
853 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
854}
855
Jeff Brown6328cdc2010-07-29 18:18:33 -0700856void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
857 int32_t scanCode, uint32_t policyFlags) {
858 int32_t newMetaState;
859 nsecs_t downTime;
860 bool metaStateChanged = false;
861
862 { // acquire lock
863 AutoMutex _l(mLock);
864
865 if (down) {
866 // Rotate key codes according to orientation if needed.
867 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
868 if (mAssociatedDisplayId >= 0) {
869 int32_t orientation;
870 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
871 return;
872 }
873
874 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700875 }
876
Jeff Brown6328cdc2010-07-29 18:18:33 -0700877 // Add key down.
878 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
879 if (keyDownIndex >= 0) {
880 // key repeat, be sure to use same keycode as before in case of rotation
881 keyCode = mLocked.keyDowns.top().keyCode;
882 } else {
883 // key down
884 mLocked.keyDowns.push();
885 KeyDown& keyDown = mLocked.keyDowns.editTop();
886 keyDown.keyCode = keyCode;
887 keyDown.scanCode = scanCode;
888 }
889
890 mLocked.downTime = when;
891 } else {
892 // Remove key down.
893 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
894 if (keyDownIndex >= 0) {
895 // key up, be sure to use same keycode as before in case of rotation
896 keyCode = mLocked.keyDowns.top().keyCode;
897 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
898 } else {
899 // key was not actually down
900 LOGI("Dropping key up from device %s because the key was not down. "
901 "keyCode=%d, scanCode=%d",
902 getDeviceName().string(), keyCode, scanCode);
903 return;
904 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700905 }
906
Jeff Brown6328cdc2010-07-29 18:18:33 -0700907 int32_t oldMetaState = mLocked.metaState;
908 newMetaState = updateMetaState(keyCode, down, oldMetaState);
909 if (oldMetaState != newMetaState) {
910 mLocked.metaState = newMetaState;
911 metaStateChanged = true;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700912 }
Jeff Brownfd035822010-06-30 16:10:35 -0700913
Jeff Brown6328cdc2010-07-29 18:18:33 -0700914 downTime = mLocked.downTime;
915 } // release lock
916
917 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700918 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700919 }
920
Jeff Brown6328cdc2010-07-29 18:18:33 -0700921 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
922}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700923
Jeff Brown6328cdc2010-07-29 18:18:33 -0700924void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
925 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700926 int32_t policyActions = getPolicy()->interceptKey(when,
927 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700928
Jeff Brown6d0fec22010-07-23 21:28:06 -0700929 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700930 return; // event dropped
931 }
932
Jeff Brown6328cdc2010-07-29 18:18:33 -0700933 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700934 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700935 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700936 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700937 }
938
Jeff Brown6d0fec22010-07-23 21:28:06 -0700939 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown6328cdc2010-07-29 18:18:33 -0700940 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700941}
942
Jeff Brown6328cdc2010-07-29 18:18:33 -0700943ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
944 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700945 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700946 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700947 return i;
948 }
949 }
950 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700951}
952
Jeff Brown6d0fec22010-07-23 21:28:06 -0700953int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
954 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
955}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700956
Jeff Brown6d0fec22010-07-23 21:28:06 -0700957int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
958 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
959}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700960
Jeff Brown6d0fec22010-07-23 21:28:06 -0700961bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
962 const int32_t* keyCodes, uint8_t* outFlags) {
963 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
964}
965
966int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700967 { // acquire lock
968 AutoMutex _l(mLock);
969 return mLocked.metaState;
970 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700971}
972
973
974// --- TrackballInputMapper ---
975
976TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
977 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
978 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
979 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
980 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
981 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
982
Jeff Brown6328cdc2010-07-29 18:18:33 -0700983 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700984}
985
986TrackballInputMapper::~TrackballInputMapper() {
987}
988
989uint32_t TrackballInputMapper::getSources() {
990 return AINPUT_SOURCE_TRACKBALL;
991}
992
993void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
994 InputMapper::populateDeviceInfo(info);
995
996 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
997 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
998}
999
Jeff Brown6328cdc2010-07-29 18:18:33 -07001000void TrackballInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001001 mAccumulator.clear();
1002
Jeff Brown6328cdc2010-07-29 18:18:33 -07001003 mLocked.down = false;
1004 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001005}
1006
1007void TrackballInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001008 for (;;) {
1009 { // acquire lock
1010 AutoMutex _l(mLock);
1011
1012 if (! mLocked.down) {
1013 initializeLocked();
1014 break; // done
1015 }
1016 } // release lock
1017
1018 // Synthesize trackball button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001019 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001020 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001021 mAccumulator.btnMouse = false;
1022 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001023 }
1024
Jeff Brown6d0fec22010-07-23 21:28:06 -07001025 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001026}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001027
Jeff Brown6d0fec22010-07-23 21:28:06 -07001028void TrackballInputMapper::process(const RawEvent* rawEvent) {
1029 switch (rawEvent->type) {
1030 case EV_KEY:
1031 switch (rawEvent->scanCode) {
1032 case BTN_MOUSE:
1033 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1034 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001035 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1036 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001037 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001038 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001039 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001040 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001041
Jeff Brown6d0fec22010-07-23 21:28:06 -07001042 case EV_REL:
1043 switch (rawEvent->scanCode) {
1044 case REL_X:
1045 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1046 mAccumulator.relX = rawEvent->value;
1047 break;
1048 case REL_Y:
1049 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1050 mAccumulator.relY = rawEvent->value;
1051 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001052 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001053 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001054
Jeff Brown6d0fec22010-07-23 21:28:06 -07001055 case EV_SYN:
1056 switch (rawEvent->scanCode) {
1057 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001058 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001059 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001060 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001061 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001062 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001063}
1064
Jeff Brown6d0fec22010-07-23 21:28:06 -07001065void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001066 uint32_t fields = mAccumulator.fields;
1067 if (fields == 0) {
1068 return; // no new state changes, so nothing to do
1069 }
1070
Jeff Brown6328cdc2010-07-29 18:18:33 -07001071 int motionEventAction;
1072 PointerCoords pointerCoords;
1073 nsecs_t downTime;
1074 { // acquire lock
1075 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001076
Jeff Brown6328cdc2010-07-29 18:18:33 -07001077 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1078
1079 if (downChanged) {
1080 if (mAccumulator.btnMouse) {
1081 mLocked.down = true;
1082 mLocked.downTime = when;
1083 } else {
1084 mLocked.down = false;
1085 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001086 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001087
Jeff Brown6328cdc2010-07-29 18:18:33 -07001088 downTime = mLocked.downTime;
1089 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1090 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001091
Jeff Brown6328cdc2010-07-29 18:18:33 -07001092 if (downChanged) {
1093 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001094 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001095 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001096 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001097
Jeff Brown6328cdc2010-07-29 18:18:33 -07001098 pointerCoords.x = x;
1099 pointerCoords.y = y;
1100 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1101 pointerCoords.size = 0;
1102 pointerCoords.touchMajor = 0;
1103 pointerCoords.touchMinor = 0;
1104 pointerCoords.toolMajor = 0;
1105 pointerCoords.toolMinor = 0;
1106 pointerCoords.orientation = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001107
Jeff Brown6328cdc2010-07-29 18:18:33 -07001108 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1109 // Rotate motion based on display orientation if needed.
1110 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1111 int32_t orientation;
1112 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1113 return;
1114 }
1115
1116 float temp;
1117 switch (orientation) {
1118 case InputReaderPolicyInterface::ROTATION_90:
1119 temp = pointerCoords.x;
1120 pointerCoords.x = pointerCoords.y;
1121 pointerCoords.y = - temp;
1122 break;
1123
1124 case InputReaderPolicyInterface::ROTATION_180:
1125 pointerCoords.x = - pointerCoords.x;
1126 pointerCoords.y = - pointerCoords.y;
1127 break;
1128
1129 case InputReaderPolicyInterface::ROTATION_270:
1130 temp = pointerCoords.x;
1131 pointerCoords.x = - pointerCoords.y;
1132 pointerCoords.y = temp;
1133 break;
1134 }
1135 }
1136 } // release lock
1137
1138 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001139
1140 mAccumulator.clear();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001141}
1142
1143void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1144 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001145 uint32_t policyFlags = 0;
1146 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1147
1148 if (! applyStandardPolicyActions(when, policyActions)) {
1149 return; // event dropped
1150 }
1151
Jeff Brown6d0fec22010-07-23 21:28:06 -07001152 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001153 int32_t pointerId = 0;
1154
Jeff Brown6d0fec22010-07-23 21:28:06 -07001155 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07001156 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001157 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001158}
1159
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001160int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1161 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1162 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1163 } else {
1164 return AKEY_STATE_UNKNOWN;
1165 }
1166}
1167
Jeff Brown6d0fec22010-07-23 21:28:06 -07001168
1169// --- TouchInputMapper ---
1170
1171TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brown6328cdc2010-07-29 18:18:33 -07001172 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1173 mLocked.surfaceOrientation = -1;
1174 mLocked.surfaceWidth = -1;
1175 mLocked.surfaceHeight = -1;
1176
1177 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001178}
1179
1180TouchInputMapper::~TouchInputMapper() {
1181}
1182
1183uint32_t TouchInputMapper::getSources() {
1184 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1185}
1186
1187void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1188 InputMapper::populateDeviceInfo(info);
1189
Jeff Brown6328cdc2010-07-29 18:18:33 -07001190 { // acquire lock
1191 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001192
Jeff Brown6328cdc2010-07-29 18:18:33 -07001193 // Ensure surface information is up to date so that orientation changes are
1194 // noticed immediately.
1195 configureSurfaceLocked();
1196
1197 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1198 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001199
1200 if (mLocked.orientedRanges.havePressure) {
1201 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1202 mLocked.orientedRanges.pressure);
1203 }
1204
1205 if (mLocked.orientedRanges.haveSize) {
1206 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1207 mLocked.orientedRanges.size);
1208 }
1209
1210 if (mLocked.orientedRanges.haveTouchArea) {
1211 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1212 mLocked.orientedRanges.touchMajor);
1213 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1214 mLocked.orientedRanges.touchMinor);
1215 }
1216
1217 if (mLocked.orientedRanges.haveToolArea) {
1218 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1219 mLocked.orientedRanges.toolMajor);
1220 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1221 mLocked.orientedRanges.toolMinor);
1222 }
1223
1224 if (mLocked.orientedRanges.haveOrientation) {
1225 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1226 mLocked.orientedRanges.orientation);
1227 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001228 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001229}
1230
Jeff Brown6328cdc2010-07-29 18:18:33 -07001231void TouchInputMapper::initializeLocked() {
1232 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001233 mLastTouch.clear();
1234 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001235
1236 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1237 mAveragingTouchFilter.historyStart[i] = 0;
1238 mAveragingTouchFilter.historyEnd[i] = 0;
1239 }
1240
1241 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001242
1243 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001244
1245 mLocked.orientedRanges.havePressure = false;
1246 mLocked.orientedRanges.haveSize = false;
1247 mLocked.orientedRanges.haveTouchArea = false;
1248 mLocked.orientedRanges.haveToolArea = false;
1249 mLocked.orientedRanges.haveOrientation = false;
1250}
1251
1252static void logAxisInfo(RawAbsoluteAxisInfo axis, const char* name) {
1253 if (axis.valid) {
1254 LOGI(INDENT "Raw %s axis: min=%d, max=%d, flat=%d, fuzz=%d",
1255 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1256 } else {
1257 LOGI(INDENT "Raw %s axis: unknown range", name);
1258 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001259}
1260
1261void TouchInputMapper::configure() {
1262 InputMapper::configure();
1263
1264 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001265 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001266
1267 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001268 configureRawAxes();
1269 logRawAxes();
1270
1271 // Prepare input device calibration.
1272 parseCalibration();
1273 resolveCalibration();
1274 logCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001275
Jeff Brown6328cdc2010-07-29 18:18:33 -07001276 { // acquire lock
1277 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001278
Jeff Brown8d608662010-08-30 03:02:23 -07001279 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001280 configureSurfaceLocked();
1281 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001282}
1283
Jeff Brown8d608662010-08-30 03:02:23 -07001284void TouchInputMapper::configureParameters() {
1285 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1286 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1287 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1288}
1289
1290void TouchInputMapper::configureRawAxes() {
1291 mRawAxes.x.clear();
1292 mRawAxes.y.clear();
1293 mRawAxes.pressure.clear();
1294 mRawAxes.touchMajor.clear();
1295 mRawAxes.touchMinor.clear();
1296 mRawAxes.toolMajor.clear();
1297 mRawAxes.toolMinor.clear();
1298 mRawAxes.orientation.clear();
1299}
1300
1301void TouchInputMapper::logRawAxes() {
1302 logAxisInfo(mRawAxes.x, "x");
1303 logAxisInfo(mRawAxes.y, "y");
1304 logAxisInfo(mRawAxes.pressure, "pressure");
1305 logAxisInfo(mRawAxes.touchMajor, "touchMajor");
1306 logAxisInfo(mRawAxes.touchMinor, "touchMinor");
1307 logAxisInfo(mRawAxes.toolMajor, "toolMajor");
1308 logAxisInfo(mRawAxes.toolMinor, "toolMinor");
1309 logAxisInfo(mRawAxes.orientation, "orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001310}
1311
Jeff Brown6328cdc2010-07-29 18:18:33 -07001312bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001313 // Update orientation and dimensions if needed.
1314 int32_t orientation;
1315 int32_t width, height;
1316 if (mAssociatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001317 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001318 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1319 return false;
1320 }
1321 } else {
1322 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown8d608662010-08-30 03:02:23 -07001323 width = mRawAxes.x.getRange();
1324 height = mRawAxes.y.getRange();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001325 }
1326
Jeff Brown6328cdc2010-07-29 18:18:33 -07001327 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001328 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001329 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001330 }
1331
Jeff Brown6328cdc2010-07-29 18:18:33 -07001332 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001333 if (sizeChanged) {
Jeff Brown8d608662010-08-30 03:02:23 -07001334 LOGI("Device configured: id=0x%x, name=%s (display size was changed)",
1335 getDeviceId(), getDeviceName().string());
1336
Jeff Brown6328cdc2010-07-29 18:18:33 -07001337 mLocked.surfaceWidth = width;
1338 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001339
Jeff Brown8d608662010-08-30 03:02:23 -07001340 // Configure X and Y factors.
1341 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1342 mLocked.xOrigin = mRawAxes.x.minValue;
1343 mLocked.yOrigin = mRawAxes.y.minValue;
1344 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1345 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001346 mLocked.xPrecision = 1.0f / mLocked.xScale;
1347 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001348
Jeff Brown6328cdc2010-07-29 18:18:33 -07001349 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001350 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001351 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001352 mLocked.xOrigin = 0;
1353 mLocked.yOrigin = 0;
1354 mLocked.xScale = 1.0f;
1355 mLocked.yScale = 1.0f;
1356 mLocked.xPrecision = 1.0f;
1357 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001358 }
1359
Jeff Brown8d608662010-08-30 03:02:23 -07001360 // Scale factor for terms that are not oriented in a particular axis.
1361 // If the pixels are square then xScale == yScale otherwise we fake it
1362 // by choosing an average.
1363 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001364
Jeff Brown8d608662010-08-30 03:02:23 -07001365 // Size of diagonal axis.
1366 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001367
Jeff Brown8d608662010-08-30 03:02:23 -07001368 // TouchMajor and TouchMinor factors.
1369 if (mCalibration.touchAreaCalibration != Calibration::TOUCH_AREA_CALIBRATION_NONE) {
1370 mLocked.orientedRanges.haveTouchArea = true;
1371 mLocked.orientedRanges.touchMajor.min = 0;
1372 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1373 mLocked.orientedRanges.touchMajor.flat = 0;
1374 mLocked.orientedRanges.touchMajor.fuzz = 0;
1375 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1376 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001377
Jeff Brown8d608662010-08-30 03:02:23 -07001378 // ToolMajor and ToolMinor factors.
1379 if (mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1380 mLocked.toolAreaLinearScale = 0;
1381 mLocked.toolAreaLinearBias = 0;
1382 if (mCalibration.toolAreaCalibration == Calibration::TOOL_AREA_CALIBRATION_LINEAR) {
1383 if (mCalibration.haveToolAreaLinearScale) {
1384 mLocked.toolAreaLinearScale = mCalibration.toolAreaLinearScale;
1385 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1386 mLocked.toolAreaLinearScale = float(min(width, height))
1387 / mRawAxes.toolMajor.maxValue;
1388 }
1389
1390 if (mCalibration.haveToolAreaLinearBias) {
1391 mLocked.toolAreaLinearBias = mCalibration.toolAreaLinearBias;
1392 }
1393 }
1394
1395 mLocked.orientedRanges.haveToolArea = true;
1396 mLocked.orientedRanges.toolMajor.min = 0;
1397 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1398 mLocked.orientedRanges.toolMajor.flat = 0;
1399 mLocked.orientedRanges.toolMajor.fuzz = 0;
1400 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1401 }
1402
1403 // Pressure factors.
1404 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1405 RawAbsoluteAxisInfo rawPressureAxis;
1406 switch (mCalibration.pressureSource) {
1407 case Calibration::PRESSURE_SOURCE_PRESSURE:
1408 rawPressureAxis = mRawAxes.pressure;
1409 break;
1410 case Calibration::PRESSURE_SOURCE_TOUCH:
1411 rawPressureAxis = mRawAxes.touchMajor;
1412 break;
1413 default:
1414 rawPressureAxis.clear();
1415 }
1416
1417 mLocked.pressureScale = 0;
1418 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1419 || mCalibration.pressureCalibration
1420 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1421 if (mCalibration.havePressureScale) {
1422 mLocked.pressureScale = mCalibration.pressureScale;
1423 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1424 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1425 }
1426 }
1427
1428 mLocked.orientedRanges.havePressure = true;
1429 mLocked.orientedRanges.pressure.min = 0;
1430 mLocked.orientedRanges.pressure.max = 1.0;
1431 mLocked.orientedRanges.pressure.flat = 0;
1432 mLocked.orientedRanges.pressure.fuzz = 0;
1433 }
1434
1435 // Size factors.
1436 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
1437 mLocked.sizeScale = 0;
1438 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1439 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1440 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1441 }
1442 }
1443
1444 mLocked.orientedRanges.haveSize = true;
1445 mLocked.orientedRanges.size.min = 0;
1446 mLocked.orientedRanges.size.max = 1.0;
1447 mLocked.orientedRanges.size.flat = 0;
1448 mLocked.orientedRanges.size.fuzz = 0;
1449 }
1450
1451 // Orientation
1452 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
1453 mLocked.orientationScale = 0;
1454 if (mCalibration.orientationCalibration
1455 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1456 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1457 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1458 }
1459 }
1460
1461 mLocked.orientedRanges.orientation.min = - M_PI_2;
1462 mLocked.orientedRanges.orientation.max = M_PI_2;
1463 mLocked.orientedRanges.orientation.flat = 0;
1464 mLocked.orientedRanges.orientation.fuzz = 0;
1465 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001466 }
1467
1468 if (orientationChanged || sizeChanged) {
1469 // Compute oriented surface dimensions, precision, and scales.
1470 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001471 switch (mLocked.surfaceOrientation) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001472 case InputReaderPolicyInterface::ROTATION_90:
1473 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001474 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1475 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1476 mLocked.orientedXPrecision = mLocked.yPrecision;
1477 mLocked.orientedYPrecision = mLocked.xPrecision;
1478 orientedXScale = mLocked.yScale;
1479 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001480 break;
1481 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001482 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1483 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1484 mLocked.orientedXPrecision = mLocked.xPrecision;
1485 mLocked.orientedYPrecision = mLocked.yPrecision;
1486 orientedXScale = mLocked.xScale;
1487 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001488 break;
1489 }
1490
1491 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001492 mLocked.orientedRanges.x.min = 0;
1493 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1494 mLocked.orientedRanges.x.flat = 0;
1495 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001496
Jeff Brown6328cdc2010-07-29 18:18:33 -07001497 mLocked.orientedRanges.y.min = 0;
1498 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1499 mLocked.orientedRanges.y.flat = 0;
1500 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001501 }
1502
1503 return true;
1504}
1505
Jeff Brown6328cdc2010-07-29 18:18:33 -07001506void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001507 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001508
Jeff Brown6328cdc2010-07-29 18:18:33 -07001509 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown8d608662010-08-30 03:02:23 -07001510 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001511 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1512
Jeff Brown6328cdc2010-07-29 18:18:33 -07001513 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001514
Jeff Brown6328cdc2010-07-29 18:18:33 -07001515 if (virtualKeyDefinitions.size() == 0) {
1516 return;
1517 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001518
Jeff Brown6328cdc2010-07-29 18:18:33 -07001519 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1520
Jeff Brown8d608662010-08-30 03:02:23 -07001521 int32_t touchScreenLeft = mRawAxes.x.minValue;
1522 int32_t touchScreenTop = mRawAxes.y.minValue;
1523 int32_t touchScreenWidth = mRawAxes.x.getRange();
1524 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001525
1526 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001527 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001528 virtualKeyDefinitions[i];
1529
1530 mLocked.virtualKeys.add();
1531 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1532
1533 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1534 int32_t keyCode;
1535 uint32_t flags;
1536 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1537 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001538 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1539 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001540 mLocked.virtualKeys.pop(); // drop the key
1541 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001542 }
1543
Jeff Brown6328cdc2010-07-29 18:18:33 -07001544 virtualKey.keyCode = keyCode;
1545 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001546
Jeff Brown6328cdc2010-07-29 18:18:33 -07001547 // convert the key definition's display coordinates into touch coordinates for a hit box
1548 int32_t halfWidth = virtualKeyDefinition.width / 2;
1549 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001550
Jeff Brown6328cdc2010-07-29 18:18:33 -07001551 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1552 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1553 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1554 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1555 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1556 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1557 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1558 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001559
Jeff Brown8d608662010-08-30 03:02:23 -07001560 LOGI(INDENT "VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
Jeff Brown6328cdc2010-07-29 18:18:33 -07001561 virtualKey.scanCode, virtualKey.keyCode,
1562 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1563 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001564}
1565
Jeff Brown8d608662010-08-30 03:02:23 -07001566void TouchInputMapper::parseCalibration() {
1567 const InputDeviceCalibration& in = getDevice()->getCalibration();
1568 Calibration& out = mCalibration;
1569
1570 // Touch Area
1571 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_DEFAULT;
1572 String8 touchAreaCalibrationString;
1573 if (in.tryGetProperty(String8("touch.touchArea.calibration"), touchAreaCalibrationString)) {
1574 if (touchAreaCalibrationString == "none") {
1575 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1576 } else if (touchAreaCalibrationString == "geometric") {
1577 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC;
1578 } else if (touchAreaCalibrationString == "pressure") {
1579 out.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1580 } else if (touchAreaCalibrationString != "default") {
1581 LOGW("Invalid value for touch.touchArea.calibration: '%s'",
1582 touchAreaCalibrationString.string());
1583 }
1584 }
1585
1586 // Tool Area
1587 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_DEFAULT;
1588 String8 toolAreaCalibrationString;
1589 if (in.tryGetProperty(String8("tool.toolArea.calibration"), toolAreaCalibrationString)) {
1590 if (toolAreaCalibrationString == "none") {
1591 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1592 } else if (toolAreaCalibrationString == "geometric") {
1593 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC;
1594 } else if (toolAreaCalibrationString == "linear") {
1595 out.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1596 } else if (toolAreaCalibrationString != "default") {
1597 LOGW("Invalid value for tool.toolArea.calibration: '%s'",
1598 toolAreaCalibrationString.string());
1599 }
1600 }
1601
1602 out.haveToolAreaLinearScale = in.tryGetProperty(String8("touch.toolArea.linearScale"),
1603 out.toolAreaLinearScale);
1604 out.haveToolAreaLinearBias = in.tryGetProperty(String8("touch.toolArea.linearBias"),
1605 out.toolAreaLinearBias);
1606 out.haveToolAreaIsSummed = in.tryGetProperty(String8("touch.toolArea.isSummed"),
1607 out.toolAreaIsSummed);
1608
1609 // Pressure
1610 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1611 String8 pressureCalibrationString;
1612 if (in.tryGetProperty(String8("tool.pressure.calibration"), pressureCalibrationString)) {
1613 if (pressureCalibrationString == "none") {
1614 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1615 } else if (pressureCalibrationString == "physical") {
1616 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1617 } else if (pressureCalibrationString == "amplitude") {
1618 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1619 } else if (pressureCalibrationString != "default") {
1620 LOGW("Invalid value for tool.pressure.calibration: '%s'",
1621 pressureCalibrationString.string());
1622 }
1623 }
1624
1625 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1626 String8 pressureSourceString;
1627 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1628 if (pressureSourceString == "pressure") {
1629 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1630 } else if (pressureSourceString == "touch") {
1631 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1632 } else if (pressureSourceString != "default") {
1633 LOGW("Invalid value for touch.pressure.source: '%s'",
1634 pressureSourceString.string());
1635 }
1636 }
1637
1638 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1639 out.pressureScale);
1640
1641 // Size
1642 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1643 String8 sizeCalibrationString;
1644 if (in.tryGetProperty(String8("tool.size.calibration"), sizeCalibrationString)) {
1645 if (sizeCalibrationString == "none") {
1646 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1647 } else if (sizeCalibrationString == "normalized") {
1648 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1649 } else if (sizeCalibrationString != "default") {
1650 LOGW("Invalid value for tool.size.calibration: '%s'",
1651 sizeCalibrationString.string());
1652 }
1653 }
1654
1655 // Orientation
1656 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1657 String8 orientationCalibrationString;
1658 if (in.tryGetProperty(String8("tool.orientation.calibration"), orientationCalibrationString)) {
1659 if (orientationCalibrationString == "none") {
1660 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1661 } else if (orientationCalibrationString == "interpolated") {
1662 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1663 } else if (orientationCalibrationString != "default") {
1664 LOGW("Invalid value for tool.orientation.calibration: '%s'",
1665 orientationCalibrationString.string());
1666 }
1667 }
1668}
1669
1670void TouchInputMapper::resolveCalibration() {
1671 // Pressure
1672 switch (mCalibration.pressureSource) {
1673 case Calibration::PRESSURE_SOURCE_DEFAULT:
1674 if (mRawAxes.pressure.valid) {
1675 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1676 } else if (mRawAxes.touchMajor.valid) {
1677 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1678 }
1679 break;
1680
1681 case Calibration::PRESSURE_SOURCE_PRESSURE:
1682 if (! mRawAxes.pressure.valid) {
1683 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1684 "the pressure axis is not available.");
1685 }
1686 break;
1687
1688 case Calibration::PRESSURE_SOURCE_TOUCH:
1689 if (! mRawAxes.touchMajor.valid) {
1690 LOGW("Calibration property touch.pressure.source is 'touch' but "
1691 "the touchMajor axis is not available.");
1692 }
1693 break;
1694
1695 default:
1696 break;
1697 }
1698
1699 switch (mCalibration.pressureCalibration) {
1700 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1701 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1702 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1703 } else {
1704 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1705 }
1706 break;
1707
1708 default:
1709 break;
1710 }
1711
1712 // Tool Area
1713 switch (mCalibration.toolAreaCalibration) {
1714 case Calibration::TOOL_AREA_CALIBRATION_DEFAULT:
1715 if (mRawAxes.toolMajor.valid) {
1716 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_LINEAR;
1717 } else {
1718 mCalibration.toolAreaCalibration = Calibration::TOOL_AREA_CALIBRATION_NONE;
1719 }
1720 break;
1721
1722 default:
1723 break;
1724 }
1725
1726 // Touch Area
1727 switch (mCalibration.touchAreaCalibration) {
1728 case Calibration::TOUCH_AREA_CALIBRATION_DEFAULT:
1729 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
1730 && mCalibration.toolAreaCalibration != Calibration::TOOL_AREA_CALIBRATION_NONE) {
1731 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_PRESSURE;
1732 } else {
1733 mCalibration.touchAreaCalibration = Calibration::TOUCH_AREA_CALIBRATION_NONE;
1734 }
1735 break;
1736
1737 default:
1738 break;
1739 }
1740
1741 // Size
1742 switch (mCalibration.sizeCalibration) {
1743 case Calibration::SIZE_CALIBRATION_DEFAULT:
1744 if (mRawAxes.toolMajor.valid) {
1745 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1746 } else {
1747 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1748 }
1749 break;
1750
1751 default:
1752 break;
1753 }
1754
1755 // Orientation
1756 switch (mCalibration.orientationCalibration) {
1757 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1758 if (mRawAxes.orientation.valid) {
1759 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1760 } else {
1761 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1762 }
1763 break;
1764
1765 default:
1766 break;
1767 }
1768}
1769
1770void TouchInputMapper::logCalibration() {
1771 // Touch Area
1772 switch (mCalibration.touchAreaCalibration) {
1773 case Calibration::TOUCH_AREA_CALIBRATION_NONE:
1774 LOGI(INDENT " touch.touchArea.calibration: none");
1775 break;
1776 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
1777 LOGI(INDENT " touch.touchArea.calibration: geometric");
1778 break;
1779 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
1780 LOGI(INDENT " touch.touchArea.calibration: pressure");
1781 break;
1782 default:
1783 assert(false);
1784 }
1785
1786 // Tool Area
1787 switch (mCalibration.toolAreaCalibration) {
1788 case Calibration::TOOL_AREA_CALIBRATION_NONE:
1789 LOGI(INDENT " touch.toolArea.calibration: none");
1790 break;
1791 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
1792 LOGI(INDENT " touch.toolArea.calibration: geometric");
1793 break;
1794 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
1795 LOGI(INDENT " touch.toolArea.calibration: linear");
1796 break;
1797 default:
1798 assert(false);
1799 }
1800
1801 if (mCalibration.haveToolAreaLinearScale) {
1802 LOGI(INDENT " touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale);
1803 }
1804
1805 if (mCalibration.haveToolAreaLinearBias) {
1806 LOGI(INDENT " touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias);
1807 }
1808
1809 if (mCalibration.haveToolAreaIsSummed) {
1810 LOGI(INDENT " touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed);
1811 }
1812
1813 // Pressure
1814 switch (mCalibration.pressureCalibration) {
1815 case Calibration::PRESSURE_CALIBRATION_NONE:
1816 LOGI(INDENT " touch.pressure.calibration: none");
1817 break;
1818 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
1819 LOGI(INDENT " touch.pressure.calibration: physical");
1820 break;
1821 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
1822 LOGI(INDENT " touch.pressure.calibration: amplitude");
1823 break;
1824 default:
1825 assert(false);
1826 }
1827
1828 switch (mCalibration.pressureSource) {
1829 case Calibration::PRESSURE_SOURCE_PRESSURE:
1830 LOGI(INDENT " touch.pressure.source: pressure");
1831 break;
1832 case Calibration::PRESSURE_SOURCE_TOUCH:
1833 LOGI(INDENT " touch.pressure.source: touch");
1834 break;
1835 case Calibration::PRESSURE_SOURCE_DEFAULT:
1836 break;
1837 default:
1838 assert(false);
1839 }
1840
1841 if (mCalibration.havePressureScale) {
1842 LOGI(INDENT " touch.pressure.scale: %f", mCalibration.pressureScale);
1843 }
1844
1845 // Size
1846 switch (mCalibration.sizeCalibration) {
1847 case Calibration::SIZE_CALIBRATION_NONE:
1848 LOGI(INDENT " touch.size.calibration: none");
1849 break;
1850 case Calibration::SIZE_CALIBRATION_NORMALIZED:
1851 LOGI(INDENT " touch.size.calibration: normalized");
1852 break;
1853 default:
1854 assert(false);
1855 }
1856
1857 // Orientation
1858 switch (mCalibration.orientationCalibration) {
1859 case Calibration::ORIENTATION_CALIBRATION_NONE:
1860 LOGI(INDENT " touch.orientation.calibration: none");
1861 break;
1862 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
1863 LOGI(INDENT " touch.orientation.calibration: interpolated");
1864 break;
1865 default:
1866 assert(false);
1867 }
1868}
1869
Jeff Brown6d0fec22010-07-23 21:28:06 -07001870void TouchInputMapper::reset() {
1871 // Synthesize touch up event if touch is currently down.
1872 // This will also take care of finishing virtual key processing if needed.
1873 if (mLastTouch.pointerCount != 0) {
1874 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1875 mCurrentTouch.clear();
1876 syncTouch(when, true);
1877 }
1878
Jeff Brown6328cdc2010-07-29 18:18:33 -07001879 { // acquire lock
1880 AutoMutex _l(mLock);
1881 initializeLocked();
1882 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001883
Jeff Brown6328cdc2010-07-29 18:18:33 -07001884 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001885}
1886
1887void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001888 // Apply generic policy actions.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001889
1890 uint32_t policyFlags = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001891 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1892
1893 if (! applyStandardPolicyActions(when, policyActions)) {
1894 mLastTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001895 return; // event dropped
1896 }
1897
Jeff Brown6328cdc2010-07-29 18:18:33 -07001898 // Preprocess pointer data.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001899
Jeff Brown6d0fec22010-07-23 21:28:06 -07001900 if (mParameters.useBadTouchFilter) {
1901 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001902 havePointerIds = false;
1903 }
1904 }
1905
Jeff Brown6d0fec22010-07-23 21:28:06 -07001906 if (mParameters.useJumpyTouchFilter) {
1907 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001908 havePointerIds = false;
1909 }
1910 }
1911
1912 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001913 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001914 }
1915
Jeff Brown6d0fec22010-07-23 21:28:06 -07001916 TouchData temp;
1917 TouchData* savedTouch;
1918 if (mParameters.useAveragingTouchFilter) {
1919 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001920 savedTouch = & temp;
1921
Jeff Brown6d0fec22010-07-23 21:28:06 -07001922 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001923 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001924 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001925 }
1926
Jeff Brown6328cdc2010-07-29 18:18:33 -07001927 // Process touches and virtual keys.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001928
Jeff Brown6d0fec22010-07-23 21:28:06 -07001929 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
1930 if (touchResult == DISPATCH_TOUCH) {
1931 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001932 }
1933
Jeff Brown6328cdc2010-07-29 18:18:33 -07001934 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001935
Jeff Brown6d0fec22010-07-23 21:28:06 -07001936 if (touchResult == DROP_STROKE) {
1937 mLastTouch.clear();
1938 } else {
1939 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001940 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001941}
1942
Jeff Brown6d0fec22010-07-23 21:28:06 -07001943TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
1944 nsecs_t when, uint32_t policyFlags) {
1945 int32_t keyEventAction, keyEventFlags;
1946 int32_t keyCode, scanCode, downTime;
1947 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07001948
Jeff Brown6328cdc2010-07-29 18:18:33 -07001949 { // acquire lock
1950 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001951
Jeff Brown6328cdc2010-07-29 18:18:33 -07001952 // Update surface size and orientation, including virtual key positions.
1953 if (! configureSurfaceLocked()) {
1954 return DROP_STROKE;
1955 }
1956
1957 // Check for virtual key press.
1958 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001959 if (mCurrentTouch.pointerCount == 0) {
1960 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001961 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001962#if DEBUG_VIRTUAL_KEYS
1963 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1964 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1965#endif
1966 keyEventAction = AKEY_EVENT_ACTION_UP;
1967 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1968 touchResult = SKIP_TOUCH;
1969 goto DispatchVirtualKey;
1970 }
1971
1972 if (mCurrentTouch.pointerCount == 1) {
1973 int32_t x = mCurrentTouch.pointers[0].x;
1974 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001975 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
1976 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001977 // Pointer is still within the space of the virtual key.
1978 return SKIP_TOUCH;
1979 }
1980 }
1981
1982 // Pointer left virtual key area or another pointer also went down.
1983 // Send key cancellation and drop the stroke so subsequent motions will be
1984 // considered fresh downs. This is useful when the user swipes away from the
1985 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001986 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001987#if DEBUG_VIRTUAL_KEYS
1988 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1989 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1990#endif
1991 keyEventAction = AKEY_EVENT_ACTION_UP;
1992 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1993 | AKEY_EVENT_FLAG_CANCELED;
1994 touchResult = DROP_STROKE;
1995 goto DispatchVirtualKey;
1996 } else {
1997 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
1998 // Pointer just went down. Handle off-screen touches, if needed.
1999 int32_t x = mCurrentTouch.pointers[0].x;
2000 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002001 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002002 // If exactly one pointer went down, check for virtual key hit.
2003 // Otherwise we will drop the entire stroke.
2004 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002005 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002006 if (virtualKey) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002007 mLocked.currentVirtualKey.down = true;
2008 mLocked.currentVirtualKey.downTime = when;
2009 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2010 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002011#if DEBUG_VIRTUAL_KEYS
2012 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
2013 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
2014#endif
2015 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2016 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2017 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2018 touchResult = SKIP_TOUCH;
2019 goto DispatchVirtualKey;
2020 }
2021 }
2022 return DROP_STROKE;
2023 }
2024 }
2025 return DISPATCH_TOUCH;
2026 }
2027
2028 DispatchVirtualKey:
2029 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002030 keyCode = mLocked.currentVirtualKey.keyCode;
2031 scanCode = mLocked.currentVirtualKey.scanCode;
2032 downTime = mLocked.currentVirtualKey.downTime;
2033 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002034
2035 // Dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002036 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
2037 keyCode, scanCode, downTime);
2038 return touchResult;
2039}
2040
2041void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
2042 int32_t keyEventAction, int32_t keyEventFlags,
2043 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002044 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002045
Jeff Brownc5ed5912010-07-14 18:48:53 -07002046 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002047 getPolicy()->virtualKeyDownFeedback();
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002048 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002049
Jeff Brown6d0fec22010-07-23 21:28:06 -07002050 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brownc5ed5912010-07-14 18:48:53 -07002051 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -07002052
Jeff Brown6d0fec22010-07-23 21:28:06 -07002053 if (applyStandardPolicyActions(when, policyActions)) {
2054 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -07002055 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2056 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002057}
2058
Jeff Brown6d0fec22010-07-23 21:28:06 -07002059void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2060 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2061 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002062 if (currentPointerCount == 0 && lastPointerCount == 0) {
2063 return; // nothing to do!
2064 }
2065
Jeff Brown6d0fec22010-07-23 21:28:06 -07002066 BitSet32 currentIdBits = mCurrentTouch.idBits;
2067 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002068
2069 if (currentIdBits == lastIdBits) {
2070 // No pointer id changes so this is a move event.
2071 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002072 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002073 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002074 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002075 } else {
2076 // There may be pointers going up and pointers going down at the same time when pointer
2077 // ids are reported by the device driver.
2078 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2079 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2080 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002081 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002082
2083 while (! upIdBits.isEmpty()) {
2084 uint32_t upId = upIdBits.firstMarkedBit();
2085 upIdBits.clearBit(upId);
2086 BitSet32 oldActiveIdBits = activeIdBits;
2087 activeIdBits.clearBit(upId);
2088
2089 int32_t motionEventAction;
2090 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002091 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002092 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002093 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002094 }
2095
Jeff Brown6d0fec22010-07-23 21:28:06 -07002096 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002097 oldActiveIdBits, upId, pointerCount, motionEventAction);
2098 pointerCount -= 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002099 }
2100
2101 while (! downIdBits.isEmpty()) {
2102 uint32_t downId = downIdBits.firstMarkedBit();
2103 downIdBits.clearBit(downId);
2104 BitSet32 oldActiveIdBits = activeIdBits;
2105 activeIdBits.markBit(downId);
2106
2107 int32_t motionEventAction;
2108 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002109 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002110 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002111 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002112 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002113 }
2114
Jeff Brown8d608662010-08-30 03:02:23 -07002115 pointerCount += 1;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002116 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002117 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002118 }
2119 }
2120}
2121
Jeff Brown6d0fec22010-07-23 21:28:06 -07002122void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002123 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002124 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002125 int32_t pointerIds[MAX_POINTERS];
2126 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac02010-04-22 18:58:52 -07002127 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002128 float xPrecision, yPrecision;
2129
2130 { // acquire lock
2131 AutoMutex _l(mLock);
2132
2133 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2134 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002135 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002136 uint32_t id = idBits.firstMarkedBit();
2137 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002138 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002139
Jeff Brown8d608662010-08-30 03:02:23 -07002140 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002141
Jeff Brown8d608662010-08-30 03:02:23 -07002142 // X and Y
2143 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2144 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002145
Jeff Brown8d608662010-08-30 03:02:23 -07002146 // ToolMajor and ToolMinor
2147 float toolMajor, toolMinor;
2148 switch (mCalibration.toolAreaCalibration) {
2149 case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
2150 toolMajor = in.toolMajor * mLocked.geometricScale;
2151 if (mRawAxes.toolMinor.valid) {
2152 toolMinor = in.toolMinor * mLocked.geometricScale;
2153 } else {
2154 toolMinor = toolMajor;
2155 }
2156 break;
2157 case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
2158 toolMajor = in.toolMajor != 0
2159 ? in.toolMajor * mLocked.toolAreaLinearScale + mLocked.toolAreaLinearBias
2160 : 0;
2161 if (mRawAxes.toolMinor.valid) {
2162 toolMinor = in.toolMinor != 0
2163 ? in.toolMinor * mLocked.toolAreaLinearScale
2164 + mLocked.toolAreaLinearBias
2165 : 0;
2166 } else {
2167 toolMinor = toolMajor;
2168 }
2169 break;
2170 default:
2171 toolMajor = 0;
2172 toolMinor = 0;
2173 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002174 }
2175
Jeff Brown8d608662010-08-30 03:02:23 -07002176 if (mCalibration.haveToolAreaIsSummed && mCalibration.toolAreaIsSummed) {
2177 toolMajor /= pointerCount;
2178 toolMinor /= pointerCount;
2179 }
2180
2181 // Pressure
2182 float rawPressure;
2183 switch (mCalibration.pressureSource) {
2184 case Calibration::PRESSURE_SOURCE_PRESSURE:
2185 rawPressure = in.pressure;
2186 break;
2187 case Calibration::PRESSURE_SOURCE_TOUCH:
2188 rawPressure = in.touchMajor;
2189 break;
2190 default:
2191 rawPressure = 0;
2192 }
2193
2194 float pressure;
2195 switch (mCalibration.pressureCalibration) {
2196 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2197 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2198 pressure = rawPressure * mLocked.pressureScale;
2199 break;
2200 default:
2201 pressure = 1;
2202 break;
2203 }
2204
2205 // TouchMajor and TouchMinor
2206 float touchMajor, touchMinor;
2207 switch (mCalibration.touchAreaCalibration) {
2208 case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
2209 touchMajor = in.touchMajor * mLocked.geometricScale;
2210 if (mRawAxes.touchMinor.valid) {
2211 touchMinor = in.touchMinor * mLocked.geometricScale;
2212 } else {
2213 touchMinor = touchMajor;
2214 }
2215 break;
2216 case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
2217 touchMajor = toolMajor * pressure;
2218 touchMinor = toolMinor * pressure;
2219 break;
2220 default:
2221 touchMajor = 0;
2222 touchMinor = 0;
2223 break;
2224 }
2225
2226 if (touchMajor > toolMajor) {
2227 touchMajor = toolMajor;
2228 }
2229 if (touchMinor > toolMinor) {
2230 touchMinor = toolMinor;
2231 }
2232
2233 // Size
2234 float size;
2235 switch (mCalibration.sizeCalibration) {
2236 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2237 float rawSize = mRawAxes.toolMinor.valid
2238 ? avg(in.toolMajor, in.toolMinor)
2239 : in.toolMajor;
2240 size = rawSize * mLocked.sizeScale;
2241 break;
2242 }
2243 default:
2244 size = 0;
2245 break;
2246 }
2247
2248 // Orientation
2249 float orientation;
2250 switch (mCalibration.orientationCalibration) {
2251 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2252 orientation = in.orientation * mLocked.orientationScale;
2253 break;
2254 default:
2255 orientation = 0;
2256 }
2257
2258 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002259 switch (mLocked.surfaceOrientation) {
2260 case InputReaderPolicyInterface::ROTATION_90: {
2261 float xTemp = x;
2262 x = y;
2263 y = mLocked.surfaceWidth - xTemp;
2264 orientation -= M_PI_2;
2265 if (orientation < - M_PI_2) {
2266 orientation += M_PI;
2267 }
2268 break;
2269 }
2270 case InputReaderPolicyInterface::ROTATION_180: {
2271 x = mLocked.surfaceWidth - x;
2272 y = mLocked.surfaceHeight - y;
2273 orientation = - orientation;
2274 break;
2275 }
2276 case InputReaderPolicyInterface::ROTATION_270: {
2277 float xTemp = x;
2278 x = mLocked.surfaceHeight - y;
2279 y = xTemp;
2280 orientation += M_PI_2;
2281 if (orientation > M_PI_2) {
2282 orientation -= M_PI;
2283 }
2284 break;
2285 }
2286 }
2287
Jeff Brown8d608662010-08-30 03:02:23 -07002288 // Write output coords.
2289 PointerCoords& out = pointerCoords[outIndex];
2290 out.x = x;
2291 out.y = y;
2292 out.pressure = pressure;
2293 out.size = size;
2294 out.touchMajor = touchMajor;
2295 out.touchMinor = touchMinor;
2296 out.toolMajor = toolMajor;
2297 out.toolMinor = toolMinor;
2298 out.orientation = orientation;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002299
Jeff Brown8d608662010-08-30 03:02:23 -07002300 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002301
2302 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002303 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002304 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002305 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002306
2307 // Check edge flags by looking only at the first pointer since the flags are
2308 // global to the event.
2309 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2310 if (pointerCoords[0].x <= 0) {
2311 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2312 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2313 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2314 }
2315 if (pointerCoords[0].y <= 0) {
2316 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2317 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2318 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2319 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002320 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002321
2322 xPrecision = mLocked.orientedXPrecision;
2323 yPrecision = mLocked.orientedYPrecision;
2324 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07002325
Jeff Brown6d0fec22010-07-23 21:28:06 -07002326 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002327 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002328 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002329 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002330}
2331
Jeff Brown6328cdc2010-07-29 18:18:33 -07002332bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002333 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2334 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2335 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002336 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002337 return true;
2338}
2339
Jeff Brown6328cdc2010-07-29 18:18:33 -07002340const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2341 int32_t x, int32_t y) {
2342 size_t numVirtualKeys = mLocked.virtualKeys.size();
2343 for (size_t i = 0; i < numVirtualKeys; i++) {
2344 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002345
2346#if DEBUG_VIRTUAL_KEYS
2347 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2348 "left=%d, top=%d, right=%d, bottom=%d",
2349 x, y,
2350 virtualKey.keyCode, virtualKey.scanCode,
2351 virtualKey.hitLeft, virtualKey.hitTop,
2352 virtualKey.hitRight, virtualKey.hitBottom);
2353#endif
2354
2355 if (virtualKey.isHit(x, y)) {
2356 return & virtualKey;
2357 }
2358 }
2359
2360 return NULL;
2361}
2362
2363void TouchInputMapper::calculatePointerIds() {
2364 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2365 uint32_t lastPointerCount = mLastTouch.pointerCount;
2366
2367 if (currentPointerCount == 0) {
2368 // No pointers to assign.
2369 mCurrentTouch.idBits.clear();
2370 } else if (lastPointerCount == 0) {
2371 // All pointers are new.
2372 mCurrentTouch.idBits.clear();
2373 for (uint32_t i = 0; i < currentPointerCount; i++) {
2374 mCurrentTouch.pointers[i].id = i;
2375 mCurrentTouch.idToIndex[i] = i;
2376 mCurrentTouch.idBits.markBit(i);
2377 }
2378 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2379 // Only one pointer and no change in count so it must have the same id as before.
2380 uint32_t id = mLastTouch.pointers[0].id;
2381 mCurrentTouch.pointers[0].id = id;
2382 mCurrentTouch.idToIndex[id] = 0;
2383 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2384 } else {
2385 // General case.
2386 // We build a heap of squared euclidean distances between current and last pointers
2387 // associated with the current and last pointer indices. Then, we find the best
2388 // match (by distance) for each current pointer.
2389 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2390
2391 uint32_t heapSize = 0;
2392 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2393 currentPointerIndex++) {
2394 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2395 lastPointerIndex++) {
2396 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2397 - mLastTouch.pointers[lastPointerIndex].x;
2398 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2399 - mLastTouch.pointers[lastPointerIndex].y;
2400
2401 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2402
2403 // Insert new element into the heap (sift up).
2404 heap[heapSize].currentPointerIndex = currentPointerIndex;
2405 heap[heapSize].lastPointerIndex = lastPointerIndex;
2406 heap[heapSize].distance = distance;
2407 heapSize += 1;
2408 }
2409 }
2410
2411 // Heapify
2412 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2413 startIndex -= 1;
2414 for (uint32_t parentIndex = startIndex; ;) {
2415 uint32_t childIndex = parentIndex * 2 + 1;
2416 if (childIndex >= heapSize) {
2417 break;
2418 }
2419
2420 if (childIndex + 1 < heapSize
2421 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2422 childIndex += 1;
2423 }
2424
2425 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2426 break;
2427 }
2428
2429 swap(heap[parentIndex], heap[childIndex]);
2430 parentIndex = childIndex;
2431 }
2432 }
2433
2434#if DEBUG_POINTER_ASSIGNMENT
2435 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2436 for (size_t i = 0; i < heapSize; i++) {
2437 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2438 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2439 heap[i].distance);
2440 }
2441#endif
2442
2443 // Pull matches out by increasing order of distance.
2444 // To avoid reassigning pointers that have already been matched, the loop keeps track
2445 // of which last and current pointers have been matched using the matchedXXXBits variables.
2446 // It also tracks the used pointer id bits.
2447 BitSet32 matchedLastBits(0);
2448 BitSet32 matchedCurrentBits(0);
2449 BitSet32 usedIdBits(0);
2450 bool first = true;
2451 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2452 for (;;) {
2453 if (first) {
2454 // The first time through the loop, we just consume the root element of
2455 // the heap (the one with smallest distance).
2456 first = false;
2457 } else {
2458 // Previous iterations consumed the root element of the heap.
2459 // Pop root element off of the heap (sift down).
2460 heapSize -= 1;
2461 assert(heapSize > 0);
2462
2463 // Sift down.
2464 heap[0] = heap[heapSize];
2465 for (uint32_t parentIndex = 0; ;) {
2466 uint32_t childIndex = parentIndex * 2 + 1;
2467 if (childIndex >= heapSize) {
2468 break;
2469 }
2470
2471 if (childIndex + 1 < heapSize
2472 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2473 childIndex += 1;
2474 }
2475
2476 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2477 break;
2478 }
2479
2480 swap(heap[parentIndex], heap[childIndex]);
2481 parentIndex = childIndex;
2482 }
2483
2484#if DEBUG_POINTER_ASSIGNMENT
2485 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2486 for (size_t i = 0; i < heapSize; i++) {
2487 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2488 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2489 heap[i].distance);
2490 }
2491#endif
2492 }
2493
2494 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2495 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2496
2497 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2498 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2499
2500 matchedCurrentBits.markBit(currentPointerIndex);
2501 matchedLastBits.markBit(lastPointerIndex);
2502
2503 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2504 mCurrentTouch.pointers[currentPointerIndex].id = id;
2505 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2506 usedIdBits.markBit(id);
2507
2508#if DEBUG_POINTER_ASSIGNMENT
2509 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2510 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2511#endif
2512 break;
2513 }
2514 }
2515
2516 // Assign fresh ids to new pointers.
2517 if (currentPointerCount > lastPointerCount) {
2518 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2519 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2520 uint32_t id = usedIdBits.firstUnmarkedBit();
2521
2522 mCurrentTouch.pointers[currentPointerIndex].id = id;
2523 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2524 usedIdBits.markBit(id);
2525
2526#if DEBUG_POINTER_ASSIGNMENT
2527 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2528 currentPointerIndex, id);
2529#endif
2530
2531 if (--i == 0) break; // done
2532 matchedCurrentBits.markBit(currentPointerIndex);
2533 }
2534 }
2535
2536 // Fix id bits.
2537 mCurrentTouch.idBits = usedIdBits;
2538 }
2539}
2540
2541/* Special hack for devices that have bad screen data: if one of the
2542 * points has moved more than a screen height from the last position,
2543 * then drop it. */
2544bool TouchInputMapper::applyBadTouchFilter() {
2545 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002546 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002547 return false;
2548 }
2549
2550 uint32_t pointerCount = mCurrentTouch.pointerCount;
2551
2552 // Nothing to do if there are no points.
2553 if (pointerCount == 0) {
2554 return false;
2555 }
2556
2557 // Don't do anything if a finger is going down or up. We run
2558 // here before assigning pointer IDs, so there isn't a good
2559 // way to do per-finger matching.
2560 if (pointerCount != mLastTouch.pointerCount) {
2561 return false;
2562 }
2563
2564 // We consider a single movement across more than a 7/16 of
2565 // the long size of the screen to be bad. This was a magic value
2566 // determined by looking at the maximum distance it is feasible
2567 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07002568 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002569
2570 // XXX The original code in InputDevice.java included commented out
2571 // code for testing the X axis. Note that when we drop a point
2572 // we don't actually restore the old X either. Strange.
2573 // The old code also tries to track when bad points were previously
2574 // detected but it turns out that due to the placement of a "break"
2575 // at the end of the loop, we never set mDroppedBadPoint to true
2576 // so it is effectively dead code.
2577 // Need to figure out if the old code is busted or just overcomplicated
2578 // but working as intended.
2579
2580 // Look through all new points and see if any are farther than
2581 // acceptable from all previous points.
2582 for (uint32_t i = pointerCount; i-- > 0; ) {
2583 int32_t y = mCurrentTouch.pointers[i].y;
2584 int32_t closestY = INT_MAX;
2585 int32_t closestDeltaY = 0;
2586
2587#if DEBUG_HACKS
2588 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2589#endif
2590
2591 for (uint32_t j = pointerCount; j-- > 0; ) {
2592 int32_t lastY = mLastTouch.pointers[j].y;
2593 int32_t deltaY = abs(y - lastY);
2594
2595#if DEBUG_HACKS
2596 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2597 j, lastY, deltaY);
2598#endif
2599
2600 if (deltaY < maxDeltaY) {
2601 goto SkipSufficientlyClosePoint;
2602 }
2603 if (deltaY < closestDeltaY) {
2604 closestDeltaY = deltaY;
2605 closestY = lastY;
2606 }
2607 }
2608
2609 // Must not have found a close enough match.
2610#if DEBUG_HACKS
2611 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2612 i, y, closestY, closestDeltaY, maxDeltaY);
2613#endif
2614
2615 mCurrentTouch.pointers[i].y = closestY;
2616 return true; // XXX original code only corrects one point
2617
2618 SkipSufficientlyClosePoint: ;
2619 }
2620
2621 // No change.
2622 return false;
2623}
2624
2625/* Special hack for devices that have bad screen data: drop points where
2626 * the coordinate value for one axis has jumped to the other pointer's location.
2627 */
2628bool TouchInputMapper::applyJumpyTouchFilter() {
2629 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002630 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002631 return false;
2632 }
2633
2634 uint32_t pointerCount = mCurrentTouch.pointerCount;
2635 if (mLastTouch.pointerCount != pointerCount) {
2636#if DEBUG_HACKS
2637 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2638 mLastTouch.pointerCount, pointerCount);
2639 for (uint32_t i = 0; i < pointerCount; i++) {
2640 LOGD(" Pointer %d (%d, %d)", i,
2641 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2642 }
2643#endif
2644
2645 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2646 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2647 // Just drop the first few events going from 1 to 2 pointers.
2648 // They're bad often enough that they're not worth considering.
2649 mCurrentTouch.pointerCount = 1;
2650 mJumpyTouchFilter.jumpyPointsDropped += 1;
2651
2652#if DEBUG_HACKS
2653 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2654#endif
2655 return true;
2656 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2657 // The event when we go from 2 -> 1 tends to be messed up too
2658 mCurrentTouch.pointerCount = 2;
2659 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2660 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2661 mJumpyTouchFilter.jumpyPointsDropped += 1;
2662
2663#if DEBUG_HACKS
2664 for (int32_t i = 0; i < 2; i++) {
2665 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2666 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2667 }
2668#endif
2669 return true;
2670 }
2671 }
2672 // Reset jumpy points dropped on other transitions or if limit exceeded.
2673 mJumpyTouchFilter.jumpyPointsDropped = 0;
2674
2675#if DEBUG_HACKS
2676 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2677#endif
2678 return false;
2679 }
2680
2681 // We have the same number of pointers as last time.
2682 // A 'jumpy' point is one where the coordinate value for one axis
2683 // has jumped to the other pointer's location. No need to do anything
2684 // else if we only have one pointer.
2685 if (pointerCount < 2) {
2686 return false;
2687 }
2688
2689 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07002690 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002691
2692 // We only replace the single worst jumpy point as characterized by pointer distance
2693 // in a single axis.
2694 int32_t badPointerIndex = -1;
2695 int32_t badPointerReplacementIndex = -1;
2696 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2697
2698 for (uint32_t i = pointerCount; i-- > 0; ) {
2699 int32_t x = mCurrentTouch.pointers[i].x;
2700 int32_t y = mCurrentTouch.pointers[i].y;
2701
2702#if DEBUG_HACKS
2703 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2704#endif
2705
2706 // Check if a touch point is too close to another's coordinates
2707 bool dropX = false, dropY = false;
2708 for (uint32_t j = 0; j < pointerCount; j++) {
2709 if (i == j) {
2710 continue;
2711 }
2712
2713 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2714 dropX = true;
2715 break;
2716 }
2717
2718 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2719 dropY = true;
2720 break;
2721 }
2722 }
2723 if (! dropX && ! dropY) {
2724 continue; // not jumpy
2725 }
2726
2727 // Find a replacement candidate by comparing with older points on the
2728 // complementary (non-jumpy) axis.
2729 int32_t distance = INT_MIN; // distance to be corrected
2730 int32_t replacementIndex = -1;
2731
2732 if (dropX) {
2733 // X looks too close. Find an older replacement point with a close Y.
2734 int32_t smallestDeltaY = INT_MAX;
2735 for (uint32_t j = 0; j < pointerCount; j++) {
2736 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2737 if (deltaY < smallestDeltaY) {
2738 smallestDeltaY = deltaY;
2739 replacementIndex = j;
2740 }
2741 }
2742 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2743 } else {
2744 // Y looks too close. Find an older replacement point with a close X.
2745 int32_t smallestDeltaX = INT_MAX;
2746 for (uint32_t j = 0; j < pointerCount; j++) {
2747 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2748 if (deltaX < smallestDeltaX) {
2749 smallestDeltaX = deltaX;
2750 replacementIndex = j;
2751 }
2752 }
2753 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2754 }
2755
2756 // If replacing this pointer would correct a worse error than the previous ones
2757 // considered, then use this replacement instead.
2758 if (distance > badPointerDistance) {
2759 badPointerIndex = i;
2760 badPointerReplacementIndex = replacementIndex;
2761 badPointerDistance = distance;
2762 }
2763 }
2764
2765 // Correct the jumpy pointer if one was found.
2766 if (badPointerIndex >= 0) {
2767#if DEBUG_HACKS
2768 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2769 badPointerIndex,
2770 mLastTouch.pointers[badPointerReplacementIndex].x,
2771 mLastTouch.pointers[badPointerReplacementIndex].y);
2772#endif
2773
2774 mCurrentTouch.pointers[badPointerIndex].x =
2775 mLastTouch.pointers[badPointerReplacementIndex].x;
2776 mCurrentTouch.pointers[badPointerIndex].y =
2777 mLastTouch.pointers[badPointerReplacementIndex].y;
2778 mJumpyTouchFilter.jumpyPointsDropped += 1;
2779 return true;
2780 }
2781 }
2782
2783 mJumpyTouchFilter.jumpyPointsDropped = 0;
2784 return false;
2785}
2786
2787/* Special hack for devices that have bad screen data: aggregate and
2788 * compute averages of the coordinate data, to reduce the amount of
2789 * jitter seen by applications. */
2790void TouchInputMapper::applyAveragingTouchFilter() {
2791 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2792 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2793 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2794 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07002795 int32_t pressure;
2796 switch (mCalibration.pressureSource) {
2797 case Calibration::PRESSURE_SOURCE_PRESSURE:
2798 pressure = mCurrentTouch.pointers[currentIndex].pressure;
2799 break;
2800 case Calibration::PRESSURE_SOURCE_TOUCH:
2801 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
2802 break;
2803 default:
2804 pressure = 1;
2805 break;
2806 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002807
2808 if (mLastTouch.idBits.hasBit(id)) {
2809 // Pointer was down before and is still down now.
2810 // Compute average over history trace.
2811 uint32_t start = mAveragingTouchFilter.historyStart[id];
2812 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2813
2814 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2815 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2816 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2817
2818#if DEBUG_HACKS
2819 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2820 id, distance);
2821#endif
2822
2823 if (distance < AVERAGING_DISTANCE_LIMIT) {
2824 // Increment end index in preparation for recording new historical data.
2825 end += 1;
2826 if (end > AVERAGING_HISTORY_SIZE) {
2827 end = 0;
2828 }
2829
2830 // If the end index has looped back to the start index then we have filled
2831 // the historical trace up to the desired size so we drop the historical
2832 // data at the start of the trace.
2833 if (end == start) {
2834 start += 1;
2835 if (start > AVERAGING_HISTORY_SIZE) {
2836 start = 0;
2837 }
2838 }
2839
2840 // Add the raw data to the historical trace.
2841 mAveragingTouchFilter.historyStart[id] = start;
2842 mAveragingTouchFilter.historyEnd[id] = end;
2843 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2844 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2845 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2846
2847 // Average over all historical positions in the trace by total pressure.
2848 int32_t averagedX = 0;
2849 int32_t averagedY = 0;
2850 int32_t totalPressure = 0;
2851 for (;;) {
2852 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2853 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2854 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2855 .pointers[id].pressure;
2856
2857 averagedX += historicalX * historicalPressure;
2858 averagedY += historicalY * historicalPressure;
2859 totalPressure += historicalPressure;
2860
2861 if (start == end) {
2862 break;
2863 }
2864
2865 start += 1;
2866 if (start > AVERAGING_HISTORY_SIZE) {
2867 start = 0;
2868 }
2869 }
2870
Jeff Brown8d608662010-08-30 03:02:23 -07002871 if (totalPressure != 0) {
2872 averagedX /= totalPressure;
2873 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002874
2875#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07002876 LOGD("AveragingTouchFilter: Pointer id %d - "
2877 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2878 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002879#endif
2880
Jeff Brown8d608662010-08-30 03:02:23 -07002881 mCurrentTouch.pointers[currentIndex].x = averagedX;
2882 mCurrentTouch.pointers[currentIndex].y = averagedY;
2883 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002884 } else {
2885#if DEBUG_HACKS
2886 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2887#endif
2888 }
2889 } else {
2890#if DEBUG_HACKS
2891 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2892#endif
2893 }
2894
2895 // Reset pointer history.
2896 mAveragingTouchFilter.historyStart[id] = 0;
2897 mAveragingTouchFilter.historyEnd[id] = 0;
2898 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2899 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2900 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
2901 }
2902}
2903
2904int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002905 { // acquire lock
2906 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002907
Jeff Brown6328cdc2010-07-29 18:18:33 -07002908 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002909 return AKEY_STATE_VIRTUAL;
2910 }
2911
Jeff Brown6328cdc2010-07-29 18:18:33 -07002912 size_t numVirtualKeys = mLocked.virtualKeys.size();
2913 for (size_t i = 0; i < numVirtualKeys; i++) {
2914 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002915 if (virtualKey.keyCode == keyCode) {
2916 return AKEY_STATE_UP;
2917 }
2918 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002919 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002920
2921 return AKEY_STATE_UNKNOWN;
2922}
2923
2924int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002925 { // acquire lock
2926 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002927
Jeff Brown6328cdc2010-07-29 18:18:33 -07002928 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002929 return AKEY_STATE_VIRTUAL;
2930 }
2931
Jeff Brown6328cdc2010-07-29 18:18:33 -07002932 size_t numVirtualKeys = mLocked.virtualKeys.size();
2933 for (size_t i = 0; i < numVirtualKeys; i++) {
2934 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002935 if (virtualKey.scanCode == scanCode) {
2936 return AKEY_STATE_UP;
2937 }
2938 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002939 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002940
2941 return AKEY_STATE_UNKNOWN;
2942}
2943
2944bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2945 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002946 { // acquire lock
2947 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002948
Jeff Brown6328cdc2010-07-29 18:18:33 -07002949 size_t numVirtualKeys = mLocked.virtualKeys.size();
2950 for (size_t i = 0; i < numVirtualKeys; i++) {
2951 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002952
2953 for (size_t i = 0; i < numCodes; i++) {
2954 if (virtualKey.keyCode == keyCodes[i]) {
2955 outFlags[i] = 1;
2956 }
2957 }
2958 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002959 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002960
2961 return true;
2962}
2963
2964
2965// --- SingleTouchInputMapper ---
2966
2967SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2968 TouchInputMapper(device, associatedDisplayId) {
2969 initialize();
2970}
2971
2972SingleTouchInputMapper::~SingleTouchInputMapper() {
2973}
2974
2975void SingleTouchInputMapper::initialize() {
2976 mAccumulator.clear();
2977
2978 mDown = false;
2979 mX = 0;
2980 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002981 mPressure = 0; // default to 0 for devices that don't report pressure
2982 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07002983}
2984
2985void SingleTouchInputMapper::reset() {
2986 TouchInputMapper::reset();
2987
Jeff Brown6d0fec22010-07-23 21:28:06 -07002988 initialize();
2989 }
2990
2991void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
2992 switch (rawEvent->type) {
2993 case EV_KEY:
2994 switch (rawEvent->scanCode) {
2995 case BTN_TOUCH:
2996 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
2997 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07002998 // Don't sync immediately. Wait until the next SYN_REPORT since we might
2999 // not have received valid position information yet. This logic assumes that
3000 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003001 break;
3002 }
3003 break;
3004
3005 case EV_ABS:
3006 switch (rawEvent->scanCode) {
3007 case ABS_X:
3008 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3009 mAccumulator.absX = rawEvent->value;
3010 break;
3011 case ABS_Y:
3012 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3013 mAccumulator.absY = rawEvent->value;
3014 break;
3015 case ABS_PRESSURE:
3016 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3017 mAccumulator.absPressure = rawEvent->value;
3018 break;
3019 case ABS_TOOL_WIDTH:
3020 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3021 mAccumulator.absToolWidth = rawEvent->value;
3022 break;
3023 }
3024 break;
3025
3026 case EV_SYN:
3027 switch (rawEvent->scanCode) {
3028 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003029 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003030 break;
3031 }
3032 break;
3033 }
3034}
3035
3036void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003037 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003038 if (fields == 0) {
3039 return; // no new state changes, so nothing to do
3040 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003041
3042 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3043 mDown = mAccumulator.btnTouch;
3044 }
3045
3046 if (fields & Accumulator::FIELD_ABS_X) {
3047 mX = mAccumulator.absX;
3048 }
3049
3050 if (fields & Accumulator::FIELD_ABS_Y) {
3051 mY = mAccumulator.absY;
3052 }
3053
3054 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3055 mPressure = mAccumulator.absPressure;
3056 }
3057
3058 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003059 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003060 }
3061
3062 mCurrentTouch.clear();
3063
3064 if (mDown) {
3065 mCurrentTouch.pointerCount = 1;
3066 mCurrentTouch.pointers[0].id = 0;
3067 mCurrentTouch.pointers[0].x = mX;
3068 mCurrentTouch.pointers[0].y = mY;
3069 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003070 mCurrentTouch.pointers[0].touchMajor = 0;
3071 mCurrentTouch.pointers[0].touchMinor = 0;
3072 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3073 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003074 mCurrentTouch.pointers[0].orientation = 0;
3075 mCurrentTouch.idToIndex[0] = 0;
3076 mCurrentTouch.idBits.markBit(0);
3077 }
3078
3079 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003080
3081 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003082}
3083
Jeff Brown8d608662010-08-30 03:02:23 -07003084void SingleTouchInputMapper::configureRawAxes() {
3085 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003086
Jeff Brown8d608662010-08-30 03:02:23 -07003087 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3088 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3089 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3090 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003091}
3092
3093
3094// --- MultiTouchInputMapper ---
3095
3096MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3097 TouchInputMapper(device, associatedDisplayId) {
3098 initialize();
3099}
3100
3101MultiTouchInputMapper::~MultiTouchInputMapper() {
3102}
3103
3104void MultiTouchInputMapper::initialize() {
3105 mAccumulator.clear();
3106}
3107
3108void MultiTouchInputMapper::reset() {
3109 TouchInputMapper::reset();
3110
Jeff Brown6d0fec22010-07-23 21:28:06 -07003111 initialize();
3112}
3113
3114void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3115 switch (rawEvent->type) {
3116 case EV_ABS: {
3117 uint32_t pointerIndex = mAccumulator.pointerCount;
3118 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3119
3120 switch (rawEvent->scanCode) {
3121 case ABS_MT_POSITION_X:
3122 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3123 pointer->absMTPositionX = rawEvent->value;
3124 break;
3125 case ABS_MT_POSITION_Y:
3126 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3127 pointer->absMTPositionY = rawEvent->value;
3128 break;
3129 case ABS_MT_TOUCH_MAJOR:
3130 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3131 pointer->absMTTouchMajor = rawEvent->value;
3132 break;
3133 case ABS_MT_TOUCH_MINOR:
3134 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3135 pointer->absMTTouchMinor = rawEvent->value;
3136 break;
3137 case ABS_MT_WIDTH_MAJOR:
3138 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3139 pointer->absMTWidthMajor = rawEvent->value;
3140 break;
3141 case ABS_MT_WIDTH_MINOR:
3142 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3143 pointer->absMTWidthMinor = rawEvent->value;
3144 break;
3145 case ABS_MT_ORIENTATION:
3146 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3147 pointer->absMTOrientation = rawEvent->value;
3148 break;
3149 case ABS_MT_TRACKING_ID:
3150 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3151 pointer->absMTTrackingId = rawEvent->value;
3152 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003153 case ABS_MT_PRESSURE:
3154 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3155 pointer->absMTPressure = rawEvent->value;
3156 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003157 }
3158 break;
3159 }
3160
3161 case EV_SYN:
3162 switch (rawEvent->scanCode) {
3163 case SYN_MT_REPORT: {
3164 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3165 uint32_t pointerIndex = mAccumulator.pointerCount;
3166
3167 if (mAccumulator.pointers[pointerIndex].fields) {
3168 if (pointerIndex == MAX_POINTERS) {
3169 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3170 MAX_POINTERS);
3171 } else {
3172 pointerIndex += 1;
3173 mAccumulator.pointerCount = pointerIndex;
3174 }
3175 }
3176
3177 mAccumulator.pointers[pointerIndex].clear();
3178 break;
3179 }
3180
3181 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003182 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003183 break;
3184 }
3185 break;
3186 }
3187}
3188
3189void MultiTouchInputMapper::sync(nsecs_t when) {
3190 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003191 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003192
Jeff Brown6d0fec22010-07-23 21:28:06 -07003193 uint32_t inCount = mAccumulator.pointerCount;
3194 uint32_t outCount = 0;
3195 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003196
Jeff Brown6d0fec22010-07-23 21:28:06 -07003197 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003198
Jeff Brown6d0fec22010-07-23 21:28:06 -07003199 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003200 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3201 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003202
Jeff Brown6d0fec22010-07-23 21:28:06 -07003203 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003204 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3205 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07003206 continue;
3207 }
3208
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003209 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3210 outPointer.x = inPointer.absMTPositionX;
3211 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003212
Jeff Brown8d608662010-08-30 03:02:23 -07003213 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3214 if (inPointer.absMTPressure <= 0) {
3215 // Some devices send sync packets with X / Y but with a 0 presure to indicate
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003216 // a pointer up. Drop this finger.
3217 continue;
3218 }
Jeff Brown8d608662010-08-30 03:02:23 -07003219 outPointer.pressure = inPointer.absMTPressure;
3220 } else {
3221 // Default pressure to 0 if absent.
3222 outPointer.pressure = 0;
3223 }
3224
3225 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3226 if (inPointer.absMTTouchMajor <= 0) {
3227 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3228 // a pointer going up. Drop this finger.
3229 continue;
3230 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003231 outPointer.touchMajor = inPointer.absMTTouchMajor;
3232 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003233 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003234 outPointer.touchMajor = 0;
3235 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003236
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003237 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3238 outPointer.touchMinor = inPointer.absMTTouchMinor;
3239 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003240 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003241 outPointer.touchMinor = outPointer.touchMajor;
3242 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003243
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003244 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3245 outPointer.toolMajor = inPointer.absMTWidthMajor;
3246 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003247 // Default tool area to 0 if absent.
3248 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003249 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003250
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003251 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3252 outPointer.toolMinor = inPointer.absMTWidthMinor;
3253 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003254 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003255 outPointer.toolMinor = outPointer.toolMajor;
3256 }
3257
3258 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3259 outPointer.orientation = inPointer.absMTOrientation;
3260 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003261 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003262 outPointer.orientation = 0;
3263 }
3264
Jeff Brown8d608662010-08-30 03:02:23 -07003265 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003266 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003267 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3268 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003269
Jeff Brown6d0fec22010-07-23 21:28:06 -07003270 if (id > MAX_POINTER_ID) {
3271#if DEBUG_POINTERS
3272 LOGD("Pointers: Ignoring driver provided pointer id %d because "
3273 "it is larger than max supported id %d for optimizations",
3274 id, MAX_POINTER_ID);
3275#endif
3276 havePointerIds = false;
3277 }
3278 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003279 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003280 mCurrentTouch.idToIndex[id] = outCount;
3281 mCurrentTouch.idBits.markBit(id);
3282 }
3283 } else {
3284 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003285 }
3286 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003287
Jeff Brown6d0fec22010-07-23 21:28:06 -07003288 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003289 }
3290
Jeff Brown6d0fec22010-07-23 21:28:06 -07003291 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003292
Jeff Brown6d0fec22010-07-23 21:28:06 -07003293 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003294
3295 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003296}
3297
Jeff Brown8d608662010-08-30 03:02:23 -07003298void MultiTouchInputMapper::configureRawAxes() {
3299 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003300
Jeff Brown8d608662010-08-30 03:02:23 -07003301 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3302 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3303 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3304 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3305 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3306 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3307 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3308 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003309}
3310
Jeff Brown46b9ac02010-04-22 18:58:52 -07003311
3312} // namespace android