blob: 83b382b9a7b0e6565c0b48d36b1e3b027250b2a9 [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brownf4a4ec22010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Browne839a582010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
Jeff Brown38a7fab2010-08-30 03:02:23 -070029#include <stdlib.h>
Jeff Browne839a582010-04-22 18:58:52 -070030#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070031#include <errno.h>
32#include <limits.h>
Jeff Brown5c1ed842010-07-14 18:48:53 -070033#include <math.h>
Jeff Browne839a582010-04-22 18:58:52 -070034
Jeff Brown38a7fab2010-08-30 03:02:23 -070035#define INDENT " "
Jeff Brown26c94ff2010-09-30 14:33:04 -070036#define INDENT2 " "
37#define INDENT3 " "
38#define INDENT4 " "
Jeff Brown38a7fab2010-08-30 03:02:23 -070039
Jeff Browne839a582010-04-22 18:58:52 -070040namespace android {
41
42// --- Static Functions ---
43
44template<typename T>
45inline static T abs(const T& value) {
46 return value < 0 ? - value : value;
47}
48
49template<typename T>
50inline static T min(const T& a, const T& b) {
51 return a < b ? a : b;
52}
53
Jeff Brownf4a4ec22010-06-16 01:53:36 -070054template<typename T>
55inline static void swap(T& a, T& b) {
56 T temp = a;
57 a = b;
58 b = temp;
59}
60
Jeff Brown38a7fab2010-08-30 03:02:23 -070061inline static float avg(float x, float y) {
62 return (x + y) / 2;
63}
64
65inline static float pythag(float x, float y) {
66 return sqrtf(x * x + y * y);
67}
68
Jeff Brown26c94ff2010-09-30 14:33:04 -070069static inline const char* toString(bool value) {
70 return value ? "true" : "false";
71}
72
Jeff Brownf4a4ec22010-06-16 01:53:36 -070073
Jeff Browne839a582010-04-22 18:58:52 -070074int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
75 int32_t mask;
76 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070077 case AKEYCODE_ALT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070078 mask = AMETA_ALT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070079 break;
Jeff Brown8575a872010-06-30 16:10:35 -070080 case AKEYCODE_ALT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070081 mask = AMETA_ALT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070082 break;
Jeff Brown8575a872010-06-30 16:10:35 -070083 case AKEYCODE_SHIFT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070084 mask = AMETA_SHIFT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070085 break;
Jeff Brown8575a872010-06-30 16:10:35 -070086 case AKEYCODE_SHIFT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070087 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070088 break;
Jeff Brown8575a872010-06-30 16:10:35 -070089 case AKEYCODE_SYM:
Jeff Brown5c1ed842010-07-14 18:48:53 -070090 mask = AMETA_SYM_ON;
Jeff Browne839a582010-04-22 18:58:52 -070091 break;
92 default:
93 return oldMetaState;
94 }
95
96 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brown5c1ed842010-07-14 18:48:53 -070097 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Browne839a582010-04-22 18:58:52 -070098
Jeff Brown5c1ed842010-07-14 18:48:53 -070099 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
100 newMetaState |= AMETA_ALT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700101 }
102
Jeff Brown5c1ed842010-07-14 18:48:53 -0700103 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
104 newMetaState |= AMETA_SHIFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -0700105 }
106
107 return newMetaState;
108}
109
110static const int32_t keyCodeRotationMap[][4] = {
111 // key codes enumerated counter-clockwise with the original (unrotated) key first
112 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brown8575a872010-06-30 16:10:35 -0700113 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
114 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
115 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
116 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Browne839a582010-04-22 18:58:52 -0700117};
118static const int keyCodeRotationMapSize =
119 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
120
121int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700122 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-04-22 18:58:52 -0700123 for (int i = 0; i < keyCodeRotationMapSize; i++) {
124 if (keyCode == keyCodeRotationMap[i][0]) {
125 return keyCodeRotationMap[i][orientation];
126 }
127 }
128 }
129 return keyCode;
130}
131
Jeff Browne57e8952010-07-23 21:28:06 -0700132static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
133 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
134}
135
Jeff Browne839a582010-04-22 18:58:52 -0700136
Jeff Brown38a7fab2010-08-30 03:02:23 -0700137// --- InputDeviceCalibration ---
138
139InputDeviceCalibration::InputDeviceCalibration() {
140}
141
142void InputDeviceCalibration::clear() {
143 mProperties.clear();
144}
145
146void InputDeviceCalibration::addProperty(const String8& key, const String8& value) {
147 mProperties.add(key, value);
148}
149
150bool InputDeviceCalibration::tryGetProperty(const String8& key, String8& outValue) const {
151 ssize_t index = mProperties.indexOfKey(key);
152 if (index < 0) {
153 return false;
154 }
155
156 outValue = mProperties.valueAt(index);
157 return true;
158}
159
160bool InputDeviceCalibration::tryGetProperty(const String8& key, int32_t& outValue) const {
161 String8 stringValue;
162 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
163 return false;
164 }
165
166 char* end;
167 int value = strtol(stringValue.string(), & end, 10);
168 if (*end != '\0') {
169 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected an integer.",
170 key.string(), stringValue.string());
171 return false;
172 }
173 outValue = value;
174 return true;
175}
176
177bool InputDeviceCalibration::tryGetProperty(const String8& key, float& outValue) const {
178 String8 stringValue;
179 if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
180 return false;
181 }
182
183 char* end;
184 float value = strtof(stringValue.string(), & end);
185 if (*end != '\0') {
186 LOGW("Input device calibration key '%s' has invalid value '%s'. Expected a float.",
187 key.string(), stringValue.string());
188 return false;
189 }
190 outValue = value;
191 return true;
192}
193
194
Jeff Browne839a582010-04-22 18:58:52 -0700195// --- InputReader ---
196
197InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700198 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700199 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Browne57e8952010-07-23 21:28:06 -0700200 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brown7bfdb292010-10-24 14:39:33 -0700201 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700202 configureExcludedDevices();
Jeff Browne57e8952010-07-23 21:28:06 -0700203 updateGlobalMetaState();
204 updateInputConfiguration();
Jeff Browne839a582010-04-22 18:58:52 -0700205}
206
207InputReader::~InputReader() {
208 for (size_t i = 0; i < mDevices.size(); i++) {
209 delete mDevices.valueAt(i);
210 }
211}
212
213void InputReader::loopOnce() {
214 RawEvent rawEvent;
Jeff Browne57e8952010-07-23 21:28:06 -0700215 mEventHub->getEvent(& rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700216
217#if DEBUG_RAW_EVENTS
218 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
219 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
220 rawEvent.value);
221#endif
222
223 process(& rawEvent);
224}
225
226void InputReader::process(const RawEvent* rawEvent) {
227 switch (rawEvent->type) {
228 case EventHubInterface::DEVICE_ADDED:
Jeff Brown1ad00e92010-10-01 18:55:43 -0700229 addDevice(rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700230 break;
231
232 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown1ad00e92010-10-01 18:55:43 -0700233 removeDevice(rawEvent->deviceId);
234 break;
235
236 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brown3c3cc622010-10-20 15:33:38 -0700237 handleConfigurationChanged(rawEvent->when);
Jeff Browne839a582010-04-22 18:58:52 -0700238 break;
239
Jeff Browne57e8952010-07-23 21:28:06 -0700240 default:
241 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700242 break;
243 }
244}
245
Jeff Brown1ad00e92010-10-01 18:55:43 -0700246void InputReader::addDevice(int32_t deviceId) {
Jeff Browne57e8952010-07-23 21:28:06 -0700247 String8 name = mEventHub->getDeviceName(deviceId);
248 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
249
250 InputDevice* device = createDevice(deviceId, name, classes);
251 device->configure();
252
Jeff Brown38a7fab2010-08-30 03:02:23 -0700253 if (device->isIgnored()) {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700254 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", deviceId, name.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700255 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -0700256 LOGI("Device added: id=0x%x, name=%s, sources=%08x", deviceId, name.string(),
257 device->getSources());
Jeff Brown38a7fab2010-08-30 03:02:23 -0700258 }
259
Jeff Browne57e8952010-07-23 21:28:06 -0700260 bool added = false;
261 { // acquire device registry writer lock
262 RWLock::AutoWLock _wl(mDeviceRegistryLock);
263
264 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
265 if (deviceIndex < 0) {
266 mDevices.add(deviceId, device);
267 added = true;
268 }
269 } // release device registry writer lock
270
271 if (! added) {
272 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
273 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700274 return;
275 }
Jeff Browne839a582010-04-22 18:58:52 -0700276}
277
Jeff Brown1ad00e92010-10-01 18:55:43 -0700278void InputReader::removeDevice(int32_t deviceId) {
Jeff Browne57e8952010-07-23 21:28:06 -0700279 bool removed = false;
280 InputDevice* device = NULL;
281 { // acquire device registry writer lock
282 RWLock::AutoWLock _wl(mDeviceRegistryLock);
283
284 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
285 if (deviceIndex >= 0) {
286 device = mDevices.valueAt(deviceIndex);
287 mDevices.removeItemsAt(deviceIndex, 1);
288 removed = true;
289 }
290 } // release device registry writer lock
291
292 if (! removed) {
293 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700294 return;
295 }
296
Jeff Browne57e8952010-07-23 21:28:06 -0700297 if (device->isIgnored()) {
298 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
299 device->getId(), device->getName().string());
300 } else {
301 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
302 device->getId(), device->getName().string(), device->getSources());
303 }
304
Jeff Brown38a7fab2010-08-30 03:02:23 -0700305 device->reset();
306
Jeff Browne57e8952010-07-23 21:28:06 -0700307 delete device;
Jeff Browne839a582010-04-22 18:58:52 -0700308}
309
Jeff Browne57e8952010-07-23 21:28:06 -0700310InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
311 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Browne839a582010-04-22 18:58:52 -0700312
Jeff Browne57e8952010-07-23 21:28:06 -0700313 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Browne839a582010-04-22 18:58:52 -0700314
Jeff Browne57e8952010-07-23 21:28:06 -0700315 // Switch-like devices.
316 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
317 device->addMapper(new SwitchInputMapper(device));
318 }
319
320 // Keyboard-like devices.
321 uint32_t keyboardSources = 0;
322 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
323 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
324 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
325 }
326 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
327 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
328 }
329 if (classes & INPUT_DEVICE_CLASS_DPAD) {
330 keyboardSources |= AINPUT_SOURCE_DPAD;
331 }
Jeff Browne57e8952010-07-23 21:28:06 -0700332
333 if (keyboardSources != 0) {
334 device->addMapper(new KeyboardInputMapper(device,
335 associatedDisplayId, keyboardSources, keyboardType));
336 }
337
338 // Trackball-like devices.
339 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
340 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
341 }
342
343 // Touchscreen-like devices.
344 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
345 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
346 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
347 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
348 }
349
350 return device;
351}
352
353void InputReader::consumeEvent(const RawEvent* rawEvent) {
354 int32_t deviceId = rawEvent->deviceId;
355
356 { // acquire device registry reader lock
357 RWLock::AutoRLock _rl(mDeviceRegistryLock);
358
359 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
360 if (deviceIndex < 0) {
361 LOGW("Discarding event for unknown deviceId %d.", deviceId);
362 return;
363 }
364
365 InputDevice* device = mDevices.valueAt(deviceIndex);
366 if (device->isIgnored()) {
367 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
368 return;
369 }
370
371 device->process(rawEvent);
372 } // release device registry reader lock
373}
374
Jeff Brown3c3cc622010-10-20 15:33:38 -0700375void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -0700376 // Reset global meta state because it depends on the list of all configured devices.
377 updateGlobalMetaState();
378
379 // Update input configuration.
380 updateInputConfiguration();
381
382 // Enqueue configuration changed.
383 mDispatcher->notifyConfigurationChanged(when);
384}
385
386void InputReader::configureExcludedDevices() {
387 Vector<String8> excludedDeviceNames;
388 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
389
390 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
391 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
392 }
393}
394
395void InputReader::updateGlobalMetaState() {
396 { // acquire state lock
397 AutoMutex _l(mStateLock);
398
399 mGlobalMetaState = 0;
400
401 { // acquire device registry reader lock
402 RWLock::AutoRLock _rl(mDeviceRegistryLock);
403
404 for (size_t i = 0; i < mDevices.size(); i++) {
405 InputDevice* device = mDevices.valueAt(i);
406 mGlobalMetaState |= device->getMetaState();
407 }
408 } // release device registry reader lock
409 } // release state lock
410}
411
412int32_t InputReader::getGlobalMetaState() {
413 { // acquire state lock
414 AutoMutex _l(mStateLock);
415
416 return mGlobalMetaState;
417 } // release state lock
418}
419
420void InputReader::updateInputConfiguration() {
421 { // acquire state lock
422 AutoMutex _l(mStateLock);
423
424 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
425 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
426 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
427 { // acquire device registry reader lock
428 RWLock::AutoRLock _rl(mDeviceRegistryLock);
429
430 InputDeviceInfo deviceInfo;
431 for (size_t i = 0; i < mDevices.size(); i++) {
432 InputDevice* device = mDevices.valueAt(i);
433 device->getDeviceInfo(& deviceInfo);
434 uint32_t sources = deviceInfo.getSources();
435
436 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
437 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
438 }
439 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
440 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
441 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
442 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
443 }
444 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
445 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Browne839a582010-04-22 18:58:52 -0700446 }
447 }
Jeff Browne57e8952010-07-23 21:28:06 -0700448 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700449
Jeff Browne57e8952010-07-23 21:28:06 -0700450 mInputConfiguration.touchScreen = touchScreenConfig;
451 mInputConfiguration.keyboard = keyboardConfig;
452 mInputConfiguration.navigation = navigationConfig;
453 } // release state lock
454}
455
Jeff Brown7bfdb292010-10-24 14:39:33 -0700456void InputReader::disableVirtualKeysUntil(nsecs_t time) {
457 mDisableVirtualKeysTimeout = time;
458}
459
460bool InputReader::shouldDropVirtualKey(nsecs_t now,
461 InputDevice* device, int32_t keyCode, int32_t scanCode) {
462 if (now < mDisableVirtualKeysTimeout) {
463 LOGI("Dropping virtual key from device %s because virtual keys are "
464 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
465 device->getName().string(),
466 (mDisableVirtualKeysTimeout - now) * 0.000001,
467 keyCode, scanCode);
468 return true;
469 } else {
470 return false;
471 }
472}
473
Jeff Browne57e8952010-07-23 21:28:06 -0700474void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
475 { // acquire state lock
476 AutoMutex _l(mStateLock);
477
478 *outConfiguration = mInputConfiguration;
479 } // release state lock
480}
481
482status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
483 { // acquire device registry reader lock
484 RWLock::AutoRLock _rl(mDeviceRegistryLock);
485
486 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
487 if (deviceIndex < 0) {
488 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700489 }
490
Jeff Browne57e8952010-07-23 21:28:06 -0700491 InputDevice* device = mDevices.valueAt(deviceIndex);
492 if (device->isIgnored()) {
493 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700494 }
Jeff Browne57e8952010-07-23 21:28:06 -0700495
496 device->getDeviceInfo(outDeviceInfo);
497 return OK;
498 } // release device registy reader lock
499}
500
501void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
502 outDeviceIds.clear();
503
504 { // acquire device registry reader lock
505 RWLock::AutoRLock _rl(mDeviceRegistryLock);
506
507 size_t numDevices = mDevices.size();
508 for (size_t i = 0; i < numDevices; i++) {
509 InputDevice* device = mDevices.valueAt(i);
510 if (! device->isIgnored()) {
511 outDeviceIds.add(device->getId());
512 }
513 }
514 } // release device registy reader lock
515}
516
517int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
518 int32_t keyCode) {
519 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
520}
521
522int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
523 int32_t scanCode) {
524 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
525}
526
527int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
528 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
529}
530
531int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
532 GetStateFunc getStateFunc) {
533 { // acquire device registry reader lock
534 RWLock::AutoRLock _rl(mDeviceRegistryLock);
535
536 int32_t result = AKEY_STATE_UNKNOWN;
537 if (deviceId >= 0) {
538 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
539 if (deviceIndex >= 0) {
540 InputDevice* device = mDevices.valueAt(deviceIndex);
541 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
542 result = (device->*getStateFunc)(sourceMask, code);
543 }
544 }
545 } else {
546 size_t numDevices = mDevices.size();
547 for (size_t i = 0; i < numDevices; i++) {
548 InputDevice* device = mDevices.valueAt(i);
549 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
550 result = (device->*getStateFunc)(sourceMask, code);
551 if (result >= AKEY_STATE_DOWN) {
552 return result;
553 }
554 }
555 }
556 }
557 return result;
558 } // release device registy reader lock
559}
560
561bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
562 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
563 memset(outFlags, 0, numCodes);
564 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
565}
566
567bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
568 const int32_t* keyCodes, uint8_t* outFlags) {
569 { // acquire device registry reader lock
570 RWLock::AutoRLock _rl(mDeviceRegistryLock);
571 bool result = false;
572 if (deviceId >= 0) {
573 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
574 if (deviceIndex >= 0) {
575 InputDevice* device = mDevices.valueAt(deviceIndex);
576 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
577 result = device->markSupportedKeyCodes(sourceMask,
578 numCodes, keyCodes, outFlags);
579 }
580 }
581 } else {
582 size_t numDevices = mDevices.size();
583 for (size_t i = 0; i < numDevices; i++) {
584 InputDevice* device = mDevices.valueAt(i);
585 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
586 result |= device->markSupportedKeyCodes(sourceMask,
587 numCodes, keyCodes, outFlags);
588 }
589 }
590 }
591 return result;
592 } // release device registy reader lock
593}
594
Jeff Browna665ca82010-09-08 11:49:43 -0700595void InputReader::dump(String8& dump) {
Jeff Brown2806e382010-10-01 17:46:21 -0700596 mEventHub->dump(dump);
597 dump.append("\n");
598
599 dump.append("Input Reader State:\n");
600
Jeff Brown26c94ff2010-09-30 14:33:04 -0700601 { // acquire device registry reader lock
602 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Browna665ca82010-09-08 11:49:43 -0700603
Jeff Brown26c94ff2010-09-30 14:33:04 -0700604 for (size_t i = 0; i < mDevices.size(); i++) {
605 mDevices.valueAt(i)->dump(dump);
Jeff Browna665ca82010-09-08 11:49:43 -0700606 }
Jeff Brown26c94ff2010-09-30 14:33:04 -0700607 } // release device registy reader lock
Jeff Browna665ca82010-09-08 11:49:43 -0700608}
609
Jeff Browne57e8952010-07-23 21:28:06 -0700610
611// --- InputReaderThread ---
612
613InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
614 Thread(/*canCallJava*/ true), mReader(reader) {
615}
616
617InputReaderThread::~InputReaderThread() {
618}
619
620bool InputReaderThread::threadLoop() {
621 mReader->loopOnce();
622 return true;
623}
624
625
626// --- InputDevice ---
627
628InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
629 mContext(context), mId(id), mName(name), mSources(0) {
630}
631
632InputDevice::~InputDevice() {
633 size_t numMappers = mMappers.size();
634 for (size_t i = 0; i < numMappers; i++) {
635 delete mMappers[i];
636 }
637 mMappers.clear();
638}
639
Jeff Brown26c94ff2010-09-30 14:33:04 -0700640static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
641 int32_t rangeType, const char* name) {
642 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
643 if (range) {
644 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
645 name, range->min, range->max, range->flat, range->fuzz);
646 }
647}
648
649void InputDevice::dump(String8& dump) {
650 InputDeviceInfo deviceInfo;
651 getDeviceInfo(& deviceInfo);
652
653 dump.appendFormat(INDENT "Device 0x%x: %s\n", deviceInfo.getId(),
654 deviceInfo.getName().string());
655 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
656 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
657 if (!deviceInfo.getMotionRanges().isEmpty()) {
658 dump.append(INDENT2 "Motion Ranges:\n");
659 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
660 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
661 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
662 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
663 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
664 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
665 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
666 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
667 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
668 }
669
670 size_t numMappers = mMappers.size();
671 for (size_t i = 0; i < numMappers; i++) {
672 InputMapper* mapper = mMappers[i];
673 mapper->dump(dump);
674 }
675}
676
Jeff Browne57e8952010-07-23 21:28:06 -0700677void InputDevice::addMapper(InputMapper* mapper) {
678 mMappers.add(mapper);
679}
680
681void InputDevice::configure() {
Jeff Brown38a7fab2010-08-30 03:02:23 -0700682 if (! isIgnored()) {
683 mContext->getPolicy()->getInputDeviceCalibration(mName, mCalibration);
684 }
685
Jeff Browne57e8952010-07-23 21:28:06 -0700686 mSources = 0;
687
688 size_t numMappers = mMappers.size();
689 for (size_t i = 0; i < numMappers; i++) {
690 InputMapper* mapper = mMappers[i];
691 mapper->configure();
692 mSources |= mapper->getSources();
Jeff Browne839a582010-04-22 18:58:52 -0700693 }
694}
695
Jeff Browne57e8952010-07-23 21:28:06 -0700696void InputDevice::reset() {
697 size_t numMappers = mMappers.size();
698 for (size_t i = 0; i < numMappers; i++) {
699 InputMapper* mapper = mMappers[i];
700 mapper->reset();
701 }
702}
Jeff Browne839a582010-04-22 18:58:52 -0700703
Jeff Browne57e8952010-07-23 21:28:06 -0700704void InputDevice::process(const RawEvent* rawEvent) {
705 size_t numMappers = mMappers.size();
706 for (size_t i = 0; i < numMappers; i++) {
707 InputMapper* mapper = mMappers[i];
708 mapper->process(rawEvent);
709 }
710}
Jeff Browne839a582010-04-22 18:58:52 -0700711
Jeff Browne57e8952010-07-23 21:28:06 -0700712void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
713 outDeviceInfo->initialize(mId, mName);
714
715 size_t numMappers = mMappers.size();
716 for (size_t i = 0; i < numMappers; i++) {
717 InputMapper* mapper = mMappers[i];
718 mapper->populateDeviceInfo(outDeviceInfo);
719 }
720}
721
722int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
723 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
724}
725
726int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
727 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
728}
729
730int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
731 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
732}
733
734int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
735 int32_t result = AKEY_STATE_UNKNOWN;
736 size_t numMappers = mMappers.size();
737 for (size_t i = 0; i < numMappers; i++) {
738 InputMapper* mapper = mMappers[i];
739 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
740 result = (mapper->*getStateFunc)(sourceMask, code);
741 if (result >= AKEY_STATE_DOWN) {
742 return result;
743 }
744 }
745 }
746 return result;
747}
748
749bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
750 const int32_t* keyCodes, uint8_t* outFlags) {
751 bool result = false;
752 size_t numMappers = mMappers.size();
753 for (size_t i = 0; i < numMappers; i++) {
754 InputMapper* mapper = mMappers[i];
755 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
756 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
757 }
758 }
759 return result;
760}
761
762int32_t InputDevice::getMetaState() {
763 int32_t result = 0;
764 size_t numMappers = mMappers.size();
765 for (size_t i = 0; i < numMappers; i++) {
766 InputMapper* mapper = mMappers[i];
767 result |= mapper->getMetaState();
768 }
769 return result;
770}
771
772
773// --- InputMapper ---
774
775InputMapper::InputMapper(InputDevice* device) :
776 mDevice(device), mContext(device->getContext()) {
777}
778
779InputMapper::~InputMapper() {
780}
781
782void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
783 info->addSource(getSources());
784}
785
Jeff Brown26c94ff2010-09-30 14:33:04 -0700786void InputMapper::dump(String8& dump) {
787}
788
Jeff Browne57e8952010-07-23 21:28:06 -0700789void InputMapper::configure() {
790}
791
792void InputMapper::reset() {
793}
794
795int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
796 return AKEY_STATE_UNKNOWN;
797}
798
799int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
800 return AKEY_STATE_UNKNOWN;
801}
802
803int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
804 return AKEY_STATE_UNKNOWN;
805}
806
807bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
808 const int32_t* keyCodes, uint8_t* outFlags) {
809 return false;
810}
811
812int32_t InputMapper::getMetaState() {
813 return 0;
814}
815
Jeff Browne57e8952010-07-23 21:28:06 -0700816
817// --- SwitchInputMapper ---
818
819SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
820 InputMapper(device) {
821}
822
823SwitchInputMapper::~SwitchInputMapper() {
824}
825
826uint32_t SwitchInputMapper::getSources() {
827 return 0;
828}
829
830void SwitchInputMapper::process(const RawEvent* rawEvent) {
831 switch (rawEvent->type) {
832 case EV_SW:
833 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
834 break;
835 }
836}
837
838void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brown90f0cee2010-10-08 22:31:17 -0700839 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700840}
841
842int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
843 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
844}
845
846
847// --- KeyboardInputMapper ---
848
849KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
850 uint32_t sources, int32_t keyboardType) :
851 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
852 mKeyboardType(keyboardType) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700853 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700854}
855
856KeyboardInputMapper::~KeyboardInputMapper() {
857}
858
Jeff Brownb51719b2010-07-29 18:18:33 -0700859void KeyboardInputMapper::initializeLocked() {
860 mLocked.metaState = AMETA_NONE;
861 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700862}
863
864uint32_t KeyboardInputMapper::getSources() {
865 return mSources;
866}
867
868void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
869 InputMapper::populateDeviceInfo(info);
870
871 info->setKeyboardType(mKeyboardType);
872}
873
Jeff Brown26c94ff2010-09-30 14:33:04 -0700874void KeyboardInputMapper::dump(String8& dump) {
875 { // acquire lock
876 AutoMutex _l(mLock);
877 dump.append(INDENT2 "Keyboard Input Mapper:\n");
878 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
Jeff Brown26c94ff2010-09-30 14:33:04 -0700879 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
880 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
881 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
882 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
883 } // release lock
884}
885
Jeff Browne57e8952010-07-23 21:28:06 -0700886void KeyboardInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -0700887 for (;;) {
888 int32_t keyCode, scanCode;
889 { // acquire lock
890 AutoMutex _l(mLock);
891
892 // Synthesize key up event on reset if keys are currently down.
893 if (mLocked.keyDowns.isEmpty()) {
894 initializeLocked();
895 break; // done
896 }
897
898 const KeyDown& keyDown = mLocked.keyDowns.top();
899 keyCode = keyDown.keyCode;
900 scanCode = keyDown.scanCode;
901 } // release lock
902
Jeff Browne57e8952010-07-23 21:28:06 -0700903 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700904 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700905 }
906
907 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700908 getContext()->updateGlobalMetaState();
909}
910
911void KeyboardInputMapper::process(const RawEvent* rawEvent) {
912 switch (rawEvent->type) {
913 case EV_KEY: {
914 int32_t scanCode = rawEvent->scanCode;
915 if (isKeyboardOrGamepadKey(scanCode)) {
916 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
917 rawEvent->flags);
918 }
919 break;
920 }
921 }
922}
923
924bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
925 return scanCode < BTN_MOUSE
926 || scanCode >= KEY_OK
927 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
928}
929
Jeff Brownb51719b2010-07-29 18:18:33 -0700930void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
931 int32_t scanCode, uint32_t policyFlags) {
932 int32_t newMetaState;
933 nsecs_t downTime;
934 bool metaStateChanged = false;
935
936 { // acquire lock
937 AutoMutex _l(mLock);
938
939 if (down) {
940 // Rotate key codes according to orientation if needed.
941 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
942 if (mAssociatedDisplayId >= 0) {
943 int32_t orientation;
944 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
945 return;
946 }
947
948 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Browne57e8952010-07-23 21:28:06 -0700949 }
950
Jeff Brownb51719b2010-07-29 18:18:33 -0700951 // Add key down.
952 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
953 if (keyDownIndex >= 0) {
954 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown9bb3ef22010-11-17 19:16:52 -0800955 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brownb51719b2010-07-29 18:18:33 -0700956 } else {
957 // key down
Jeff Brown7bfdb292010-10-24 14:39:33 -0700958 if ((policyFlags & POLICY_FLAG_VIRTUAL)
959 && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {
960 return;
961 }
962
Jeff Brownb51719b2010-07-29 18:18:33 -0700963 mLocked.keyDowns.push();
964 KeyDown& keyDown = mLocked.keyDowns.editTop();
965 keyDown.keyCode = keyCode;
966 keyDown.scanCode = scanCode;
967 }
968
969 mLocked.downTime = when;
970 } else {
971 // Remove key down.
972 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
973 if (keyDownIndex >= 0) {
974 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown9bb3ef22010-11-17 19:16:52 -0800975 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brownb51719b2010-07-29 18:18:33 -0700976 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
977 } else {
978 // key was not actually down
979 LOGI("Dropping key up from device %s because the key was not down. "
980 "keyCode=%d, scanCode=%d",
981 getDeviceName().string(), keyCode, scanCode);
982 return;
983 }
Jeff Browne57e8952010-07-23 21:28:06 -0700984 }
985
Jeff Brownb51719b2010-07-29 18:18:33 -0700986 int32_t oldMetaState = mLocked.metaState;
987 newMetaState = updateMetaState(keyCode, down, oldMetaState);
988 if (oldMetaState != newMetaState) {
989 mLocked.metaState = newMetaState;
990 metaStateChanged = true;
Jeff Browne57e8952010-07-23 21:28:06 -0700991 }
Jeff Brown8575a872010-06-30 16:10:35 -0700992
Jeff Brownb51719b2010-07-29 18:18:33 -0700993 downTime = mLocked.downTime;
994 } // release lock
995
996 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700997 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700998 }
999
Jeff Browne57e8952010-07-23 21:28:06 -07001000 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown90f0cee2010-10-08 22:31:17 -07001001 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1002 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -07001003}
1004
Jeff Brownb51719b2010-07-29 18:18:33 -07001005ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1006 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -07001007 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001008 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07001009 return i;
1010 }
1011 }
1012 return -1;
Jeff Browne839a582010-04-22 18:58:52 -07001013}
1014
Jeff Browne57e8952010-07-23 21:28:06 -07001015int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1016 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1017}
Jeff Browne839a582010-04-22 18:58:52 -07001018
Jeff Browne57e8952010-07-23 21:28:06 -07001019int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1020 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1021}
Jeff Browne839a582010-04-22 18:58:52 -07001022
Jeff Browne57e8952010-07-23 21:28:06 -07001023bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1024 const int32_t* keyCodes, uint8_t* outFlags) {
1025 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1026}
1027
1028int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001029 { // acquire lock
1030 AutoMutex _l(mLock);
1031 return mLocked.metaState;
1032 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001033}
1034
1035
1036// --- TrackballInputMapper ---
1037
1038TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1039 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1040 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1041 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1042 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1043 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1044
Jeff Brownb51719b2010-07-29 18:18:33 -07001045 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001046}
1047
1048TrackballInputMapper::~TrackballInputMapper() {
1049}
1050
1051uint32_t TrackballInputMapper::getSources() {
1052 return AINPUT_SOURCE_TRACKBALL;
1053}
1054
1055void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1056 InputMapper::populateDeviceInfo(info);
1057
1058 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1059 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1060}
1061
Jeff Brown26c94ff2010-09-30 14:33:04 -07001062void TrackballInputMapper::dump(String8& dump) {
1063 { // acquire lock
1064 AutoMutex _l(mLock);
1065 dump.append(INDENT2 "Trackball Input Mapper:\n");
1066 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1067 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1068 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1069 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1070 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1071 } // release lock
1072}
1073
Jeff Brownb51719b2010-07-29 18:18:33 -07001074void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001075 mAccumulator.clear();
1076
Jeff Brownb51719b2010-07-29 18:18:33 -07001077 mLocked.down = false;
1078 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001079}
1080
1081void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-07-29 18:18:33 -07001082 for (;;) {
1083 { // acquire lock
1084 AutoMutex _l(mLock);
1085
1086 if (! mLocked.down) {
1087 initializeLocked();
1088 break; // done
1089 }
1090 } // release lock
1091
1092 // Synthesize trackball button up event on reset.
Jeff Browne57e8952010-07-23 21:28:06 -07001093 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -07001094 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -07001095 mAccumulator.btnMouse = false;
1096 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -07001097 }
1098
Jeff Browne57e8952010-07-23 21:28:06 -07001099 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001100}
Jeff Browne839a582010-04-22 18:58:52 -07001101
Jeff Browne57e8952010-07-23 21:28:06 -07001102void TrackballInputMapper::process(const RawEvent* rawEvent) {
1103 switch (rawEvent->type) {
1104 case EV_KEY:
1105 switch (rawEvent->scanCode) {
1106 case BTN_MOUSE:
1107 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1108 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07001109 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1110 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -07001111 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001112 break;
Jeff Browne839a582010-04-22 18:58:52 -07001113 }
Jeff Browne57e8952010-07-23 21:28:06 -07001114 break;
Jeff Browne839a582010-04-22 18:58:52 -07001115
Jeff Browne57e8952010-07-23 21:28:06 -07001116 case EV_REL:
1117 switch (rawEvent->scanCode) {
1118 case REL_X:
1119 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1120 mAccumulator.relX = rawEvent->value;
1121 break;
1122 case REL_Y:
1123 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1124 mAccumulator.relY = rawEvent->value;
1125 break;
Jeff Browne839a582010-04-22 18:58:52 -07001126 }
Jeff Browne57e8952010-07-23 21:28:06 -07001127 break;
Jeff Browne839a582010-04-22 18:58:52 -07001128
Jeff Browne57e8952010-07-23 21:28:06 -07001129 case EV_SYN:
1130 switch (rawEvent->scanCode) {
1131 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07001132 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07001133 break;
Jeff Browne839a582010-04-22 18:58:52 -07001134 }
Jeff Browne57e8952010-07-23 21:28:06 -07001135 break;
Jeff Browne839a582010-04-22 18:58:52 -07001136 }
Jeff Browne839a582010-04-22 18:58:52 -07001137}
1138
Jeff Browne57e8952010-07-23 21:28:06 -07001139void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -07001140 uint32_t fields = mAccumulator.fields;
1141 if (fields == 0) {
1142 return; // no new state changes, so nothing to do
1143 }
1144
Jeff Brownb51719b2010-07-29 18:18:33 -07001145 int motionEventAction;
1146 PointerCoords pointerCoords;
1147 nsecs_t downTime;
1148 { // acquire lock
1149 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001150
Jeff Brownb51719b2010-07-29 18:18:33 -07001151 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1152
1153 if (downChanged) {
1154 if (mAccumulator.btnMouse) {
1155 mLocked.down = true;
1156 mLocked.downTime = when;
1157 } else {
1158 mLocked.down = false;
1159 }
Jeff Browne57e8952010-07-23 21:28:06 -07001160 }
Jeff Browne839a582010-04-22 18:58:52 -07001161
Jeff Brownb51719b2010-07-29 18:18:33 -07001162 downTime = mLocked.downTime;
1163 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1164 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001165
Jeff Brownb51719b2010-07-29 18:18:33 -07001166 if (downChanged) {
1167 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001168 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001169 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001170 }
Jeff Browne839a582010-04-22 18:58:52 -07001171
Jeff Brownb51719b2010-07-29 18:18:33 -07001172 pointerCoords.x = x;
1173 pointerCoords.y = y;
1174 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1175 pointerCoords.size = 0;
1176 pointerCoords.touchMajor = 0;
1177 pointerCoords.touchMinor = 0;
1178 pointerCoords.toolMajor = 0;
1179 pointerCoords.toolMinor = 0;
1180 pointerCoords.orientation = 0;
Jeff Browne839a582010-04-22 18:58:52 -07001181
Jeff Brownb51719b2010-07-29 18:18:33 -07001182 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1183 // Rotate motion based on display orientation if needed.
1184 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1185 int32_t orientation;
1186 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1187 return;
1188 }
1189
1190 float temp;
1191 switch (orientation) {
1192 case InputReaderPolicyInterface::ROTATION_90:
1193 temp = pointerCoords.x;
1194 pointerCoords.x = pointerCoords.y;
1195 pointerCoords.y = - temp;
1196 break;
1197
1198 case InputReaderPolicyInterface::ROTATION_180:
1199 pointerCoords.x = - pointerCoords.x;
1200 pointerCoords.y = - pointerCoords.y;
1201 break;
1202
1203 case InputReaderPolicyInterface::ROTATION_270:
1204 temp = pointerCoords.x;
1205 pointerCoords.x = - pointerCoords.y;
1206 pointerCoords.y = temp;
1207 break;
1208 }
1209 }
1210 } // release lock
1211
Jeff Browne57e8952010-07-23 21:28:06 -07001212 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001213 int32_t pointerId = 0;
Jeff Brown90f0cee2010-10-08 22:31:17 -07001214 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
Jeff Brownaf30ff62010-09-01 17:01:00 -07001215 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown90f0cee2010-10-08 22:31:17 -07001216 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1217
1218 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001219}
1220
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001221int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1222 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1223 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1224 } else {
1225 return AKEY_STATE_UNKNOWN;
1226 }
1227}
1228
Jeff Browne57e8952010-07-23 21:28:06 -07001229
1230// --- TouchInputMapper ---
1231
1232TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001233 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1234 mLocked.surfaceOrientation = -1;
1235 mLocked.surfaceWidth = -1;
1236 mLocked.surfaceHeight = -1;
1237
1238 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001239}
1240
1241TouchInputMapper::~TouchInputMapper() {
1242}
1243
1244uint32_t TouchInputMapper::getSources() {
1245 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1246}
1247
1248void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1249 InputMapper::populateDeviceInfo(info);
1250
Jeff Brownb51719b2010-07-29 18:18:33 -07001251 { // acquire lock
1252 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001253
Jeff Brownb51719b2010-07-29 18:18:33 -07001254 // Ensure surface information is up to date so that orientation changes are
1255 // noticed immediately.
1256 configureSurfaceLocked();
1257
1258 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1259 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001260
1261 if (mLocked.orientedRanges.havePressure) {
1262 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1263 mLocked.orientedRanges.pressure);
1264 }
1265
1266 if (mLocked.orientedRanges.haveSize) {
1267 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1268 mLocked.orientedRanges.size);
1269 }
1270
Jeff Brown6b337e72010-10-14 21:42:15 -07001271 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001272 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1273 mLocked.orientedRanges.touchMajor);
1274 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1275 mLocked.orientedRanges.touchMinor);
1276 }
1277
Jeff Brown6b337e72010-10-14 21:42:15 -07001278 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001279 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1280 mLocked.orientedRanges.toolMajor);
1281 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1282 mLocked.orientedRanges.toolMinor);
1283 }
1284
1285 if (mLocked.orientedRanges.haveOrientation) {
1286 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1287 mLocked.orientedRanges.orientation);
1288 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001289 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001290}
1291
Jeff Brown26c94ff2010-09-30 14:33:04 -07001292void TouchInputMapper::dump(String8& dump) {
1293 { // acquire lock
1294 AutoMutex _l(mLock);
1295 dump.append(INDENT2 "Touch Input Mapper:\n");
1296 dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
1297 dumpParameters(dump);
1298 dumpVirtualKeysLocked(dump);
1299 dumpRawAxes(dump);
1300 dumpCalibration(dump);
1301 dumpSurfaceLocked(dump);
Jeff Brown6b337e72010-10-14 21:42:15 -07001302 dump.appendFormat(INDENT3 "Translation and Scaling Factors:");
1303 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1304 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1305 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1306 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1307 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1308 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1309 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1310 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1311 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1312 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1313 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1314 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1315 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1316 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brown26c94ff2010-09-30 14:33:04 -07001317 } // release lock
1318}
1319
Jeff Brownb51719b2010-07-29 18:18:33 -07001320void TouchInputMapper::initializeLocked() {
1321 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001322 mLastTouch.clear();
1323 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001324
1325 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1326 mAveragingTouchFilter.historyStart[i] = 0;
1327 mAveragingTouchFilter.historyEnd[i] = 0;
1328 }
1329
1330 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001331
1332 mLocked.currentVirtualKey.down = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001333
1334 mLocked.orientedRanges.havePressure = false;
1335 mLocked.orientedRanges.haveSize = false;
Jeff Brown6b337e72010-10-14 21:42:15 -07001336 mLocked.orientedRanges.haveTouchSize = false;
1337 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001338 mLocked.orientedRanges.haveOrientation = false;
1339}
1340
Jeff Browne57e8952010-07-23 21:28:06 -07001341void TouchInputMapper::configure() {
1342 InputMapper::configure();
1343
1344 // Configure basic parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001345 configureParameters();
Jeff Browne57e8952010-07-23 21:28:06 -07001346
1347 // Configure absolute axis information.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001348 configureRawAxes();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001349
1350 // Prepare input device calibration.
1351 parseCalibration();
1352 resolveCalibration();
Jeff Browne57e8952010-07-23 21:28:06 -07001353
Jeff Brownb51719b2010-07-29 18:18:33 -07001354 { // acquire lock
1355 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001356
Jeff Brown38a7fab2010-08-30 03:02:23 -07001357 // Configure surface dimensions and orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07001358 configureSurfaceLocked();
1359 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001360}
1361
Jeff Brown38a7fab2010-08-30 03:02:23 -07001362void TouchInputMapper::configureParameters() {
1363 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1364 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1365 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brown7bfdb292010-10-24 14:39:33 -07001366 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown38a7fab2010-08-30 03:02:23 -07001367}
1368
Jeff Brown26c94ff2010-09-30 14:33:04 -07001369void TouchInputMapper::dumpParameters(String8& dump) {
1370 dump.appendFormat(INDENT3 "UseBadTouchFilter: %s\n",
1371 toString(mParameters.useBadTouchFilter));
1372 dump.appendFormat(INDENT3 "UseAveragingTouchFilter: %s\n",
1373 toString(mParameters.useAveragingTouchFilter));
1374 dump.appendFormat(INDENT3 "UseJumpyTouchFilter: %s\n",
1375 toString(mParameters.useJumpyTouchFilter));
Jeff Browna665ca82010-09-08 11:49:43 -07001376}
1377
Jeff Brown38a7fab2010-08-30 03:02:23 -07001378void TouchInputMapper::configureRawAxes() {
1379 mRawAxes.x.clear();
1380 mRawAxes.y.clear();
1381 mRawAxes.pressure.clear();
1382 mRawAxes.touchMajor.clear();
1383 mRawAxes.touchMinor.clear();
1384 mRawAxes.toolMajor.clear();
1385 mRawAxes.toolMinor.clear();
1386 mRawAxes.orientation.clear();
1387}
1388
Jeff Brown26c94ff2010-09-30 14:33:04 -07001389static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Browna665ca82010-09-08 11:49:43 -07001390 if (axis.valid) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001391 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Browna665ca82010-09-08 11:49:43 -07001392 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1393 } else {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001394 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Browna665ca82010-09-08 11:49:43 -07001395 }
1396}
1397
Jeff Brown26c94ff2010-09-30 14:33:04 -07001398void TouchInputMapper::dumpRawAxes(String8& dump) {
1399 dump.append(INDENT3 "Raw Axes:\n");
1400 dumpAxisInfo(dump, mRawAxes.x, "X");
1401 dumpAxisInfo(dump, mRawAxes.y, "Y");
1402 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1403 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1404 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1405 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1406 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1407 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Browne57e8952010-07-23 21:28:06 -07001408}
1409
Jeff Brownb51719b2010-07-29 18:18:33 -07001410bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001411 // Update orientation and dimensions if needed.
1412 int32_t orientation;
1413 int32_t width, height;
1414 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001415 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001416 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1417 return false;
1418 }
1419 } else {
1420 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001421 width = mRawAxes.x.getRange();
1422 height = mRawAxes.y.getRange();
Jeff Browne57e8952010-07-23 21:28:06 -07001423 }
1424
Jeff Brownb51719b2010-07-29 18:18:33 -07001425 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001426 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001427 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001428 }
1429
Jeff Brownb51719b2010-07-29 18:18:33 -07001430 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001431 if (sizeChanged) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07001432 LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
1433 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001434
Jeff Brownb51719b2010-07-29 18:18:33 -07001435 mLocked.surfaceWidth = width;
1436 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001437
Jeff Brown38a7fab2010-08-30 03:02:23 -07001438 // Configure X and Y factors.
1439 if (mRawAxes.x.valid && mRawAxes.y.valid) {
1440 mLocked.xOrigin = mRawAxes.x.minValue;
1441 mLocked.yOrigin = mRawAxes.y.minValue;
1442 mLocked.xScale = float(width) / mRawAxes.x.getRange();
1443 mLocked.yScale = float(height) / mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001444 mLocked.xPrecision = 1.0f / mLocked.xScale;
1445 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001446
Jeff Brownb51719b2010-07-29 18:18:33 -07001447 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001448 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001449 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brownb51719b2010-07-29 18:18:33 -07001450 mLocked.xOrigin = 0;
1451 mLocked.yOrigin = 0;
1452 mLocked.xScale = 1.0f;
1453 mLocked.yScale = 1.0f;
1454 mLocked.xPrecision = 1.0f;
1455 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001456 }
1457
Jeff Brown38a7fab2010-08-30 03:02:23 -07001458 // Scale factor for terms that are not oriented in a particular axis.
1459 // If the pixels are square then xScale == yScale otherwise we fake it
1460 // by choosing an average.
1461 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001462
Jeff Brown38a7fab2010-08-30 03:02:23 -07001463 // Size of diagonal axis.
1464 float diagonalSize = pythag(width, height);
Jeff Browne57e8952010-07-23 21:28:06 -07001465
Jeff Brown38a7fab2010-08-30 03:02:23 -07001466 // TouchMajor and TouchMinor factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001467 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1468 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001469 mLocked.orientedRanges.touchMajor.min = 0;
1470 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1471 mLocked.orientedRanges.touchMajor.flat = 0;
1472 mLocked.orientedRanges.touchMajor.fuzz = 0;
1473 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1474 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001475
Jeff Brown38a7fab2010-08-30 03:02:23 -07001476 // ToolMajor and ToolMinor factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001477 mLocked.toolSizeLinearScale = 0;
1478 mLocked.toolSizeLinearBias = 0;
1479 mLocked.toolSizeAreaScale = 0;
1480 mLocked.toolSizeAreaBias = 0;
1481 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1482 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1483 if (mCalibration.haveToolSizeLinearScale) {
1484 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001485 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brown6b337e72010-10-14 21:42:15 -07001486 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown38a7fab2010-08-30 03:02:23 -07001487 / mRawAxes.toolMajor.maxValue;
1488 }
1489
Jeff Brown6b337e72010-10-14 21:42:15 -07001490 if (mCalibration.haveToolSizeLinearBias) {
1491 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1492 }
1493 } else if (mCalibration.toolSizeCalibration ==
1494 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1495 if (mCalibration.haveToolSizeLinearScale) {
1496 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1497 } else {
1498 mLocked.toolSizeLinearScale = min(width, height);
1499 }
1500
1501 if (mCalibration.haveToolSizeLinearBias) {
1502 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1503 }
1504
1505 if (mCalibration.haveToolSizeAreaScale) {
1506 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1507 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1508 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1509 }
1510
1511 if (mCalibration.haveToolSizeAreaBias) {
1512 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001513 }
1514 }
1515
Jeff Brown6b337e72010-10-14 21:42:15 -07001516 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001517 mLocked.orientedRanges.toolMajor.min = 0;
1518 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1519 mLocked.orientedRanges.toolMajor.flat = 0;
1520 mLocked.orientedRanges.toolMajor.fuzz = 0;
1521 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1522 }
1523
1524 // Pressure factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001525 mLocked.pressureScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001526 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1527 RawAbsoluteAxisInfo rawPressureAxis;
1528 switch (mCalibration.pressureSource) {
1529 case Calibration::PRESSURE_SOURCE_PRESSURE:
1530 rawPressureAxis = mRawAxes.pressure;
1531 break;
1532 case Calibration::PRESSURE_SOURCE_TOUCH:
1533 rawPressureAxis = mRawAxes.touchMajor;
1534 break;
1535 default:
1536 rawPressureAxis.clear();
1537 }
1538
Jeff Brown38a7fab2010-08-30 03:02:23 -07001539 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1540 || mCalibration.pressureCalibration
1541 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1542 if (mCalibration.havePressureScale) {
1543 mLocked.pressureScale = mCalibration.pressureScale;
1544 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1545 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1546 }
1547 }
1548
1549 mLocked.orientedRanges.havePressure = true;
1550 mLocked.orientedRanges.pressure.min = 0;
1551 mLocked.orientedRanges.pressure.max = 1.0;
1552 mLocked.orientedRanges.pressure.flat = 0;
1553 mLocked.orientedRanges.pressure.fuzz = 0;
1554 }
1555
1556 // Size factors.
Jeff Brown6b337e72010-10-14 21:42:15 -07001557 mLocked.sizeScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001558 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001559 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1560 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1561 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1562 }
1563 }
1564
1565 mLocked.orientedRanges.haveSize = true;
1566 mLocked.orientedRanges.size.min = 0;
1567 mLocked.orientedRanges.size.max = 1.0;
1568 mLocked.orientedRanges.size.flat = 0;
1569 mLocked.orientedRanges.size.fuzz = 0;
1570 }
1571
1572 // Orientation
Jeff Brown6b337e72010-10-14 21:42:15 -07001573 mLocked.orientationScale = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001574 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001575 if (mCalibration.orientationCalibration
1576 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1577 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1578 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1579 }
1580 }
1581
1582 mLocked.orientedRanges.orientation.min = - M_PI_2;
1583 mLocked.orientedRanges.orientation.max = M_PI_2;
1584 mLocked.orientedRanges.orientation.flat = 0;
1585 mLocked.orientedRanges.orientation.fuzz = 0;
1586 }
Jeff Browne57e8952010-07-23 21:28:06 -07001587 }
1588
1589 if (orientationChanged || sizeChanged) {
1590 // Compute oriented surface dimensions, precision, and scales.
1591 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001592 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001593 case InputReaderPolicyInterface::ROTATION_90:
1594 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001595 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1596 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1597 mLocked.orientedXPrecision = mLocked.yPrecision;
1598 mLocked.orientedYPrecision = mLocked.xPrecision;
1599 orientedXScale = mLocked.yScale;
1600 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001601 break;
1602 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001603 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1604 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1605 mLocked.orientedXPrecision = mLocked.xPrecision;
1606 mLocked.orientedYPrecision = mLocked.yPrecision;
1607 orientedXScale = mLocked.xScale;
1608 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001609 break;
1610 }
1611
1612 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001613 mLocked.orientedRanges.x.min = 0;
1614 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1615 mLocked.orientedRanges.x.flat = 0;
1616 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001617
Jeff Brownb51719b2010-07-29 18:18:33 -07001618 mLocked.orientedRanges.y.min = 0;
1619 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1620 mLocked.orientedRanges.y.flat = 0;
1621 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001622 }
1623
1624 return true;
1625}
1626
Jeff Brown26c94ff2010-09-30 14:33:04 -07001627void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1628 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1629 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1630 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Browna665ca82010-09-08 11:49:43 -07001631}
1632
Jeff Brownb51719b2010-07-29 18:18:33 -07001633void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001634 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Browne57e8952010-07-23 21:28:06 -07001635
Jeff Brownb51719b2010-07-29 18:18:33 -07001636 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown38a7fab2010-08-30 03:02:23 -07001637 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne57e8952010-07-23 21:28:06 -07001638 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1639
Jeff Brownb51719b2010-07-29 18:18:33 -07001640 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001641
Jeff Brownb51719b2010-07-29 18:18:33 -07001642 if (virtualKeyDefinitions.size() == 0) {
1643 return;
1644 }
Jeff Browne57e8952010-07-23 21:28:06 -07001645
Jeff Brownb51719b2010-07-29 18:18:33 -07001646 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1647
Jeff Brown38a7fab2010-08-30 03:02:23 -07001648 int32_t touchScreenLeft = mRawAxes.x.minValue;
1649 int32_t touchScreenTop = mRawAxes.y.minValue;
1650 int32_t touchScreenWidth = mRawAxes.x.getRange();
1651 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brownb51719b2010-07-29 18:18:33 -07001652
1653 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001654 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brownb51719b2010-07-29 18:18:33 -07001655 virtualKeyDefinitions[i];
1656
1657 mLocked.virtualKeys.add();
1658 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1659
1660 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1661 int32_t keyCode;
1662 uint32_t flags;
1663 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1664 & keyCode, & flags)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001665 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1666 virtualKey.scanCode);
Jeff Brownb51719b2010-07-29 18:18:33 -07001667 mLocked.virtualKeys.pop(); // drop the key
1668 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001669 }
1670
Jeff Brownb51719b2010-07-29 18:18:33 -07001671 virtualKey.keyCode = keyCode;
1672 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001673
Jeff Brownb51719b2010-07-29 18:18:33 -07001674 // convert the key definition's display coordinates into touch coordinates for a hit box
1675 int32_t halfWidth = virtualKeyDefinition.width / 2;
1676 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001677
Jeff Brownb51719b2010-07-29 18:18:33 -07001678 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1679 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1680 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1681 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1682 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1683 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1684 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1685 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001686
Jeff Brown26c94ff2010-09-30 14:33:04 -07001687 }
1688}
1689
1690void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1691 if (!mLocked.virtualKeys.isEmpty()) {
1692 dump.append(INDENT3 "Virtual Keys:\n");
1693
1694 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1695 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1696 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1697 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1698 i, virtualKey.scanCode, virtualKey.keyCode,
1699 virtualKey.hitLeft, virtualKey.hitRight,
1700 virtualKey.hitTop, virtualKey.hitBottom);
1701 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001702 }
Jeff Browne57e8952010-07-23 21:28:06 -07001703}
1704
Jeff Brown38a7fab2010-08-30 03:02:23 -07001705void TouchInputMapper::parseCalibration() {
1706 const InputDeviceCalibration& in = getDevice()->getCalibration();
1707 Calibration& out = mCalibration;
1708
Jeff Brown6b337e72010-10-14 21:42:15 -07001709 // Touch Size
1710 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1711 String8 touchSizeCalibrationString;
1712 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1713 if (touchSizeCalibrationString == "none") {
1714 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1715 } else if (touchSizeCalibrationString == "geometric") {
1716 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1717 } else if (touchSizeCalibrationString == "pressure") {
1718 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1719 } else if (touchSizeCalibrationString != "default") {
1720 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1721 touchSizeCalibrationString.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -07001722 }
1723 }
1724
Jeff Brown6b337e72010-10-14 21:42:15 -07001725 // Tool Size
1726 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1727 String8 toolSizeCalibrationString;
1728 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1729 if (toolSizeCalibrationString == "none") {
1730 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1731 } else if (toolSizeCalibrationString == "geometric") {
1732 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1733 } else if (toolSizeCalibrationString == "linear") {
1734 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1735 } else if (toolSizeCalibrationString == "area") {
1736 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1737 } else if (toolSizeCalibrationString != "default") {
1738 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1739 toolSizeCalibrationString.string());
Jeff Brown38a7fab2010-08-30 03:02:23 -07001740 }
1741 }
1742
Jeff Brown6b337e72010-10-14 21:42:15 -07001743 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1744 out.toolSizeLinearScale);
1745 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1746 out.toolSizeLinearBias);
1747 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1748 out.toolSizeAreaScale);
1749 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1750 out.toolSizeAreaBias);
1751 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1752 out.toolSizeIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001753
1754 // Pressure
1755 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1756 String8 pressureCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001757 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001758 if (pressureCalibrationString == "none") {
1759 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1760 } else if (pressureCalibrationString == "physical") {
1761 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1762 } else if (pressureCalibrationString == "amplitude") {
1763 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1764 } else if (pressureCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001765 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001766 pressureCalibrationString.string());
1767 }
1768 }
1769
1770 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1771 String8 pressureSourceString;
1772 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1773 if (pressureSourceString == "pressure") {
1774 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1775 } else if (pressureSourceString == "touch") {
1776 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1777 } else if (pressureSourceString != "default") {
1778 LOGW("Invalid value for touch.pressure.source: '%s'",
1779 pressureSourceString.string());
1780 }
1781 }
1782
1783 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1784 out.pressureScale);
1785
1786 // Size
1787 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1788 String8 sizeCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001789 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001790 if (sizeCalibrationString == "none") {
1791 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1792 } else if (sizeCalibrationString == "normalized") {
1793 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1794 } else if (sizeCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001795 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001796 sizeCalibrationString.string());
1797 }
1798 }
1799
1800 // Orientation
1801 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1802 String8 orientationCalibrationString;
Jeff Brown6b337e72010-10-14 21:42:15 -07001803 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07001804 if (orientationCalibrationString == "none") {
1805 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1806 } else if (orientationCalibrationString == "interpolated") {
1807 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1808 } else if (orientationCalibrationString != "default") {
Jeff Brown6b337e72010-10-14 21:42:15 -07001809 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown38a7fab2010-08-30 03:02:23 -07001810 orientationCalibrationString.string());
1811 }
1812 }
1813}
1814
1815void TouchInputMapper::resolveCalibration() {
1816 // Pressure
1817 switch (mCalibration.pressureSource) {
1818 case Calibration::PRESSURE_SOURCE_DEFAULT:
1819 if (mRawAxes.pressure.valid) {
1820 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1821 } else if (mRawAxes.touchMajor.valid) {
1822 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1823 }
1824 break;
1825
1826 case Calibration::PRESSURE_SOURCE_PRESSURE:
1827 if (! mRawAxes.pressure.valid) {
1828 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1829 "the pressure axis is not available.");
1830 }
1831 break;
1832
1833 case Calibration::PRESSURE_SOURCE_TOUCH:
1834 if (! mRawAxes.touchMajor.valid) {
1835 LOGW("Calibration property touch.pressure.source is 'touch' but "
1836 "the touchMajor axis is not available.");
1837 }
1838 break;
1839
1840 default:
1841 break;
1842 }
1843
1844 switch (mCalibration.pressureCalibration) {
1845 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1846 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1847 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1848 } else {
1849 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1850 }
1851 break;
1852
1853 default:
1854 break;
1855 }
1856
Jeff Brown6b337e72010-10-14 21:42:15 -07001857 // Tool Size
1858 switch (mCalibration.toolSizeCalibration) {
1859 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown38a7fab2010-08-30 03:02:23 -07001860 if (mRawAxes.toolMajor.valid) {
Jeff Brown6b337e72010-10-14 21:42:15 -07001861 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001862 } else {
Jeff Brown6b337e72010-10-14 21:42:15 -07001863 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001864 }
1865 break;
1866
1867 default:
1868 break;
1869 }
1870
Jeff Brown6b337e72010-10-14 21:42:15 -07001871 // Touch Size
1872 switch (mCalibration.touchSizeCalibration) {
1873 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown38a7fab2010-08-30 03:02:23 -07001874 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brown6b337e72010-10-14 21:42:15 -07001875 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1876 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001877 } else {
Jeff Brown6b337e72010-10-14 21:42:15 -07001878 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown38a7fab2010-08-30 03:02:23 -07001879 }
1880 break;
1881
1882 default:
1883 break;
1884 }
1885
1886 // Size
1887 switch (mCalibration.sizeCalibration) {
1888 case Calibration::SIZE_CALIBRATION_DEFAULT:
1889 if (mRawAxes.toolMajor.valid) {
1890 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1891 } else {
1892 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1893 }
1894 break;
1895
1896 default:
1897 break;
1898 }
1899
1900 // Orientation
1901 switch (mCalibration.orientationCalibration) {
1902 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
1903 if (mRawAxes.orientation.valid) {
1904 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
1905 } else {
1906 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1907 }
1908 break;
1909
1910 default:
1911 break;
1912 }
1913}
1914
Jeff Brown26c94ff2010-09-30 14:33:04 -07001915void TouchInputMapper::dumpCalibration(String8& dump) {
1916 dump.append(INDENT3 "Calibration:\n");
Jeff Browna665ca82010-09-08 11:49:43 -07001917
Jeff Brown6b337e72010-10-14 21:42:15 -07001918 // Touch Size
1919 switch (mCalibration.touchSizeCalibration) {
1920 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
1921 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001922 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001923 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
1924 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001925 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001926 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
1927 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001928 break;
1929 default:
1930 assert(false);
1931 }
1932
Jeff Brown6b337e72010-10-14 21:42:15 -07001933 // Tool Size
1934 switch (mCalibration.toolSizeCalibration) {
1935 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
1936 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001937 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001938 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
1939 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001940 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07001941 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
1942 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
1943 break;
1944 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
1945 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001946 break;
1947 default:
1948 assert(false);
1949 }
1950
Jeff Brown6b337e72010-10-14 21:42:15 -07001951 if (mCalibration.haveToolSizeLinearScale) {
1952 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
1953 mCalibration.toolSizeLinearScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001954 }
1955
Jeff Brown6b337e72010-10-14 21:42:15 -07001956 if (mCalibration.haveToolSizeLinearBias) {
1957 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
1958 mCalibration.toolSizeLinearBias);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001959 }
1960
Jeff Brown6b337e72010-10-14 21:42:15 -07001961 if (mCalibration.haveToolSizeAreaScale) {
1962 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
1963 mCalibration.toolSizeAreaScale);
1964 }
1965
1966 if (mCalibration.haveToolSizeAreaBias) {
1967 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
1968 mCalibration.toolSizeAreaBias);
1969 }
1970
1971 if (mCalibration.haveToolSizeIsSummed) {
1972 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %d\n",
1973 mCalibration.toolSizeIsSummed);
Jeff Brown38a7fab2010-08-30 03:02:23 -07001974 }
1975
1976 // Pressure
1977 switch (mCalibration.pressureCalibration) {
1978 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001979 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001980 break;
1981 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001982 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001983 break;
1984 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001985 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001986 break;
1987 default:
1988 assert(false);
1989 }
1990
1991 switch (mCalibration.pressureSource) {
1992 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001993 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001994 break;
1995 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brown26c94ff2010-09-30 14:33:04 -07001996 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07001997 break;
1998 case Calibration::PRESSURE_SOURCE_DEFAULT:
1999 break;
2000 default:
2001 assert(false);
2002 }
2003
2004 if (mCalibration.havePressureScale) {
Jeff Brown26c94ff2010-09-30 14:33:04 -07002005 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2006 mCalibration.pressureScale);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002007 }
2008
2009 // Size
2010 switch (mCalibration.sizeCalibration) {
2011 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002012 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002013 break;
2014 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002015 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002016 break;
2017 default:
2018 assert(false);
2019 }
2020
2021 // Orientation
2022 switch (mCalibration.orientationCalibration) {
2023 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002024 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002025 break;
2026 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brown26c94ff2010-09-30 14:33:04 -07002027 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown38a7fab2010-08-30 03:02:23 -07002028 break;
2029 default:
2030 assert(false);
2031 }
2032}
2033
Jeff Browne57e8952010-07-23 21:28:06 -07002034void TouchInputMapper::reset() {
2035 // Synthesize touch up event if touch is currently down.
2036 // This will also take care of finishing virtual key processing if needed.
2037 if (mLastTouch.pointerCount != 0) {
2038 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2039 mCurrentTouch.clear();
2040 syncTouch(when, true);
2041 }
2042
Jeff Brownb51719b2010-07-29 18:18:33 -07002043 { // acquire lock
2044 AutoMutex _l(mLock);
2045 initializeLocked();
2046 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002047
Jeff Brownb51719b2010-07-29 18:18:33 -07002048 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07002049}
2050
2051void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Browne839a582010-04-22 18:58:52 -07002052 uint32_t policyFlags = 0;
Jeff Browne839a582010-04-22 18:58:52 -07002053
Jeff Brownb51719b2010-07-29 18:18:33 -07002054 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07002055
Jeff Browne57e8952010-07-23 21:28:06 -07002056 if (mParameters.useBadTouchFilter) {
2057 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002058 havePointerIds = false;
2059 }
2060 }
2061
Jeff Browne57e8952010-07-23 21:28:06 -07002062 if (mParameters.useJumpyTouchFilter) {
2063 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07002064 havePointerIds = false;
2065 }
2066 }
2067
2068 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07002069 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07002070 }
2071
Jeff Browne57e8952010-07-23 21:28:06 -07002072 TouchData temp;
2073 TouchData* savedTouch;
2074 if (mParameters.useAveragingTouchFilter) {
2075 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002076 savedTouch = & temp;
2077
Jeff Browne57e8952010-07-23 21:28:06 -07002078 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07002079 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07002080 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07002081 }
2082
Jeff Brownb51719b2010-07-29 18:18:33 -07002083 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07002084
Jeff Browne57e8952010-07-23 21:28:06 -07002085 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2086 if (touchResult == DISPATCH_TOUCH) {
Jeff Brown7bfdb292010-10-24 14:39:33 -07002087 detectGestures(when);
Jeff Browne57e8952010-07-23 21:28:06 -07002088 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07002089 }
2090
Jeff Brownb51719b2010-07-29 18:18:33 -07002091 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07002092
Jeff Browne57e8952010-07-23 21:28:06 -07002093 if (touchResult == DROP_STROKE) {
2094 mLastTouch.clear();
2095 } else {
2096 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07002097 }
Jeff Browne839a582010-04-22 18:58:52 -07002098}
2099
Jeff Browne57e8952010-07-23 21:28:06 -07002100TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2101 nsecs_t when, uint32_t policyFlags) {
2102 int32_t keyEventAction, keyEventFlags;
2103 int32_t keyCode, scanCode, downTime;
2104 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07002105
Jeff Brownb51719b2010-07-29 18:18:33 -07002106 { // acquire lock
2107 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002108
Jeff Brownb51719b2010-07-29 18:18:33 -07002109 // Update surface size and orientation, including virtual key positions.
2110 if (! configureSurfaceLocked()) {
2111 return DROP_STROKE;
2112 }
2113
2114 // Check for virtual key press.
2115 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07002116 if (mCurrentTouch.pointerCount == 0) {
2117 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07002118 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002119#if DEBUG_VIRTUAL_KEYS
2120 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brown3c3cc622010-10-20 15:33:38 -07002121 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Browne57e8952010-07-23 21:28:06 -07002122#endif
2123 keyEventAction = AKEY_EVENT_ACTION_UP;
2124 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2125 touchResult = SKIP_TOUCH;
2126 goto DispatchVirtualKey;
2127 }
2128
2129 if (mCurrentTouch.pointerCount == 1) {
2130 int32_t x = mCurrentTouch.pointers[0].x;
2131 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002132 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2133 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002134 // Pointer is still within the space of the virtual key.
2135 return SKIP_TOUCH;
2136 }
2137 }
2138
2139 // Pointer left virtual key area or another pointer also went down.
2140 // Send key cancellation and drop the stroke so subsequent motions will be
2141 // considered fresh downs. This is useful when the user swipes away from the
2142 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07002143 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07002144#if DEBUG_VIRTUAL_KEYS
2145 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brown3c3cc622010-10-20 15:33:38 -07002146 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Browne57e8952010-07-23 21:28:06 -07002147#endif
2148 keyEventAction = AKEY_EVENT_ACTION_UP;
2149 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2150 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brown3c3cc622010-10-20 15:33:38 -07002151
2152 // Check whether the pointer moved inside the display area where we should
2153 // start a new stroke.
2154 int32_t x = mCurrentTouch.pointers[0].x;
2155 int32_t y = mCurrentTouch.pointers[0].y;
2156 if (isPointInsideSurfaceLocked(x, y)) {
2157 mLastTouch.clear();
2158 touchResult = DISPATCH_TOUCH;
2159 } else {
2160 touchResult = DROP_STROKE;
2161 }
Jeff Browne57e8952010-07-23 21:28:06 -07002162 } else {
2163 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2164 // Pointer just went down. Handle off-screen touches, if needed.
2165 int32_t x = mCurrentTouch.pointers[0].x;
2166 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07002167 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07002168 // If exactly one pointer went down, check for virtual key hit.
2169 // Otherwise we will drop the entire stroke.
2170 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002171 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07002172 if (virtualKey) {
Jeff Brown7bfdb292010-10-24 14:39:33 -07002173 if (mContext->shouldDropVirtualKey(when, getDevice(),
2174 virtualKey->keyCode, virtualKey->scanCode)) {
2175 return DROP_STROKE;
2176 }
2177
Jeff Brownb51719b2010-07-29 18:18:33 -07002178 mLocked.currentVirtualKey.down = true;
2179 mLocked.currentVirtualKey.downTime = when;
2180 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2181 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07002182#if DEBUG_VIRTUAL_KEYS
2183 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brown3c3cc622010-10-20 15:33:38 -07002184 mLocked.currentVirtualKey.keyCode,
2185 mLocked.currentVirtualKey.scanCode);
Jeff Browne57e8952010-07-23 21:28:06 -07002186#endif
2187 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2188 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2189 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2190 touchResult = SKIP_TOUCH;
2191 goto DispatchVirtualKey;
2192 }
2193 }
2194 return DROP_STROKE;
2195 }
2196 }
2197 return DISPATCH_TOUCH;
2198 }
2199
2200 DispatchVirtualKey:
2201 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07002202 keyCode = mLocked.currentVirtualKey.keyCode;
2203 scanCode = mLocked.currentVirtualKey.scanCode;
2204 downTime = mLocked.currentVirtualKey.downTime;
2205 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002206
2207 // Dispatch virtual key.
2208 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown956c0fb2010-10-01 14:55:30 -07002209 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brown90f0cee2010-10-08 22:31:17 -07002210 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2211 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2212 return touchResult;
Jeff Browne839a582010-04-22 18:58:52 -07002213}
2214
Jeff Brown7bfdb292010-10-24 14:39:33 -07002215void TouchInputMapper::detectGestures(nsecs_t when) {
2216 // Disable all virtual key touches that happen within a short time interval of the
2217 // most recent touch. The idea is to filter out stray virtual key presses when
2218 // interacting with the touch screen.
2219 //
2220 // Problems we're trying to solve:
2221 //
2222 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2223 // virtual key area that is implemented by a separate touch panel and accidentally
2224 // triggers a virtual key.
2225 //
2226 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2227 // area and accidentally triggers a virtual key. This often happens when virtual keys
2228 // are layed out below the screen near to where the on screen keyboard's space bar
2229 // is displayed.
2230 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2231 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2232 }
2233}
2234
Jeff Browne57e8952010-07-23 21:28:06 -07002235void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2236 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2237 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002238 if (currentPointerCount == 0 && lastPointerCount == 0) {
2239 return; // nothing to do!
2240 }
2241
Jeff Browne57e8952010-07-23 21:28:06 -07002242 BitSet32 currentIdBits = mCurrentTouch.idBits;
2243 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07002244
2245 if (currentIdBits == lastIdBits) {
2246 // No pointer id changes so this is a move event.
2247 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07002248 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07002249 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002250 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002251 } else {
Jeff Brown3c3cc622010-10-20 15:33:38 -07002252 // There may be pointers going up and pointers going down and pointers moving
2253 // all at the same time.
Jeff Browne839a582010-04-22 18:58:52 -07002254 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2255 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2256 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002257 uint32_t pointerCount = lastPointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07002258
Jeff Brown3c3cc622010-10-20 15:33:38 -07002259 // Produce an intermediate representation of the touch data that consists of the
2260 // old location of pointers that have just gone up and the new location of pointers that
2261 // have just moved but omits the location of pointers that have just gone down.
2262 TouchData interimTouch;
2263 interimTouch.copyFrom(mLastTouch);
2264
2265 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2266 bool moveNeeded = false;
2267 while (!moveIdBits.isEmpty()) {
2268 uint32_t moveId = moveIdBits.firstMarkedBit();
2269 moveIdBits.clearBit(moveId);
2270
2271 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2272 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2273 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2274 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2275 moveNeeded = true;
2276 }
2277 }
2278
2279 // Dispatch pointer up events using the interim pointer locations.
2280 while (!upIdBits.isEmpty()) {
Jeff Browne839a582010-04-22 18:58:52 -07002281 uint32_t upId = upIdBits.firstMarkedBit();
2282 upIdBits.clearBit(upId);
2283 BitSet32 oldActiveIdBits = activeIdBits;
2284 activeIdBits.clearBit(upId);
2285
2286 int32_t motionEventAction;
2287 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002288 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002289 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002290 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07002291 }
2292
Jeff Brown3c3cc622010-10-20 15:33:38 -07002293 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002294 oldActiveIdBits, upId, pointerCount, motionEventAction);
2295 pointerCount -= 1;
Jeff Browne839a582010-04-22 18:58:52 -07002296 }
2297
Jeff Brown3c3cc622010-10-20 15:33:38 -07002298 // Dispatch move events if any of the remaining pointers moved from their old locations.
2299 // Although applications receive new locations as part of individual pointer up
2300 // events, they do not generally handle them except when presented in a move event.
2301 if (moveNeeded) {
2302 dispatchTouch(when, policyFlags, &mCurrentTouch,
2303 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2304 }
2305
2306 // Dispatch pointer down events using the new pointer locations.
2307 while (!downIdBits.isEmpty()) {
Jeff Browne839a582010-04-22 18:58:52 -07002308 uint32_t downId = downIdBits.firstMarkedBit();
2309 downIdBits.clearBit(downId);
2310 BitSet32 oldActiveIdBits = activeIdBits;
2311 activeIdBits.markBit(downId);
2312
2313 int32_t motionEventAction;
2314 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07002315 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07002316 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07002317 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07002318 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07002319 }
2320
Jeff Brown38a7fab2010-08-30 03:02:23 -07002321 pointerCount += 1;
Jeff Brown3c3cc622010-10-20 15:33:38 -07002322 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002323 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07002324 }
2325 }
2326}
2327
Jeff Browne57e8952010-07-23 21:28:06 -07002328void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown38a7fab2010-08-30 03:02:23 -07002329 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Browne839a582010-04-22 18:58:52 -07002330 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07002331 int32_t pointerIds[MAX_POINTERS];
2332 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07002333 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07002334 float xPrecision, yPrecision;
2335
2336 { // acquire lock
2337 AutoMutex _l(mLock);
2338
2339 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2340 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002341 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002342 uint32_t id = idBits.firstMarkedBit();
2343 idBits.clearBit(id);
Jeff Brown38a7fab2010-08-30 03:02:23 -07002344 uint32_t inIndex = touch->idToIndex[id];
Jeff Brownb51719b2010-07-29 18:18:33 -07002345
Jeff Brown38a7fab2010-08-30 03:02:23 -07002346 const PointerData& in = touch->pointers[inIndex];
Jeff Brownb51719b2010-07-29 18:18:33 -07002347
Jeff Brown38a7fab2010-08-30 03:02:23 -07002348 // X and Y
2349 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2350 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07002351
Jeff Brown38a7fab2010-08-30 03:02:23 -07002352 // ToolMajor and ToolMinor
2353 float toolMajor, toolMinor;
Jeff Brown6b337e72010-10-14 21:42:15 -07002354 switch (mCalibration.toolSizeCalibration) {
2355 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002356 toolMajor = in.toolMajor * mLocked.geometricScale;
2357 if (mRawAxes.toolMinor.valid) {
2358 toolMinor = in.toolMinor * mLocked.geometricScale;
2359 } else {
2360 toolMinor = toolMajor;
2361 }
2362 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002363 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002364 toolMajor = in.toolMajor != 0
Jeff Brown6b337e72010-10-14 21:42:15 -07002365 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown38a7fab2010-08-30 03:02:23 -07002366 : 0;
2367 if (mRawAxes.toolMinor.valid) {
2368 toolMinor = in.toolMinor != 0
Jeff Brown6b337e72010-10-14 21:42:15 -07002369 ? in.toolMinor * mLocked.toolSizeLinearScale
2370 + mLocked.toolSizeLinearBias
Jeff Brown38a7fab2010-08-30 03:02:23 -07002371 : 0;
2372 } else {
2373 toolMinor = toolMajor;
2374 }
2375 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002376 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2377 if (in.toolMajor != 0) {
2378 float diameter = sqrtf(in.toolMajor
2379 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2380 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2381 } else {
2382 toolMajor = 0;
2383 }
2384 toolMinor = toolMajor;
2385 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07002386 default:
2387 toolMajor = 0;
2388 toolMinor = 0;
2389 break;
Jeff Brownb51719b2010-07-29 18:18:33 -07002390 }
2391
Jeff Brown6b337e72010-10-14 21:42:15 -07002392 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002393 toolMajor /= pointerCount;
2394 toolMinor /= pointerCount;
2395 }
2396
2397 // Pressure
2398 float rawPressure;
2399 switch (mCalibration.pressureSource) {
2400 case Calibration::PRESSURE_SOURCE_PRESSURE:
2401 rawPressure = in.pressure;
2402 break;
2403 case Calibration::PRESSURE_SOURCE_TOUCH:
2404 rawPressure = in.touchMajor;
2405 break;
2406 default:
2407 rawPressure = 0;
2408 }
2409
2410 float pressure;
2411 switch (mCalibration.pressureCalibration) {
2412 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2413 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2414 pressure = rawPressure * mLocked.pressureScale;
2415 break;
2416 default:
2417 pressure = 1;
2418 break;
2419 }
2420
2421 // TouchMajor and TouchMinor
2422 float touchMajor, touchMinor;
Jeff Brown6b337e72010-10-14 21:42:15 -07002423 switch (mCalibration.touchSizeCalibration) {
2424 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002425 touchMajor = in.touchMajor * mLocked.geometricScale;
2426 if (mRawAxes.touchMinor.valid) {
2427 touchMinor = in.touchMinor * mLocked.geometricScale;
2428 } else {
2429 touchMinor = touchMajor;
2430 }
2431 break;
Jeff Brown6b337e72010-10-14 21:42:15 -07002432 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown38a7fab2010-08-30 03:02:23 -07002433 touchMajor = toolMajor * pressure;
2434 touchMinor = toolMinor * pressure;
2435 break;
2436 default:
2437 touchMajor = 0;
2438 touchMinor = 0;
2439 break;
2440 }
2441
2442 if (touchMajor > toolMajor) {
2443 touchMajor = toolMajor;
2444 }
2445 if (touchMinor > toolMinor) {
2446 touchMinor = toolMinor;
2447 }
2448
2449 // Size
2450 float size;
2451 switch (mCalibration.sizeCalibration) {
2452 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2453 float rawSize = mRawAxes.toolMinor.valid
2454 ? avg(in.toolMajor, in.toolMinor)
2455 : in.toolMajor;
2456 size = rawSize * mLocked.sizeScale;
2457 break;
2458 }
2459 default:
2460 size = 0;
2461 break;
2462 }
2463
2464 // Orientation
2465 float orientation;
2466 switch (mCalibration.orientationCalibration) {
2467 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2468 orientation = in.orientation * mLocked.orientationScale;
2469 break;
2470 default:
2471 orientation = 0;
2472 }
2473
2474 // Adjust coords for orientation.
Jeff Brownb51719b2010-07-29 18:18:33 -07002475 switch (mLocked.surfaceOrientation) {
2476 case InputReaderPolicyInterface::ROTATION_90: {
2477 float xTemp = x;
2478 x = y;
2479 y = mLocked.surfaceWidth - xTemp;
2480 orientation -= M_PI_2;
2481 if (orientation < - M_PI_2) {
2482 orientation += M_PI;
2483 }
2484 break;
2485 }
2486 case InputReaderPolicyInterface::ROTATION_180: {
2487 x = mLocked.surfaceWidth - x;
2488 y = mLocked.surfaceHeight - y;
2489 orientation = - orientation;
2490 break;
2491 }
2492 case InputReaderPolicyInterface::ROTATION_270: {
2493 float xTemp = x;
2494 x = mLocked.surfaceHeight - y;
2495 y = xTemp;
2496 orientation += M_PI_2;
2497 if (orientation > M_PI_2) {
2498 orientation -= M_PI;
2499 }
2500 break;
2501 }
2502 }
2503
Jeff Brown38a7fab2010-08-30 03:02:23 -07002504 // Write output coords.
2505 PointerCoords& out = pointerCoords[outIndex];
2506 out.x = x;
2507 out.y = y;
2508 out.pressure = pressure;
2509 out.size = size;
2510 out.touchMajor = touchMajor;
2511 out.touchMinor = touchMinor;
2512 out.toolMajor = toolMajor;
2513 out.toolMinor = toolMinor;
2514 out.orientation = orientation;
Jeff Brownb51719b2010-07-29 18:18:33 -07002515
Jeff Brown38a7fab2010-08-30 03:02:23 -07002516 pointerIds[outIndex] = int32_t(id);
Jeff Brownb51719b2010-07-29 18:18:33 -07002517
2518 if (id == changedId) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002519 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brownb51719b2010-07-29 18:18:33 -07002520 }
Jeff Browne839a582010-04-22 18:58:52 -07002521 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002522
2523 // Check edge flags by looking only at the first pointer since the flags are
2524 // global to the event.
2525 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2526 if (pointerCoords[0].x <= 0) {
2527 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2528 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2529 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2530 }
2531 if (pointerCoords[0].y <= 0) {
2532 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2533 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2534 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2535 }
Jeff Browne839a582010-04-22 18:58:52 -07002536 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002537
2538 xPrecision = mLocked.orientedXPrecision;
2539 yPrecision = mLocked.orientedYPrecision;
2540 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07002541
Jeff Brown77e26fc2010-10-07 13:44:51 -07002542 getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
Jeff Brownaf30ff62010-09-01 17:01:00 -07002543 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07002544 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07002545 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07002546}
2547
Jeff Brownb51719b2010-07-29 18:18:33 -07002548bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002549 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2550 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2551 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07002552 }
Jeff Browne57e8952010-07-23 21:28:06 -07002553 return true;
2554}
2555
Jeff Brownb51719b2010-07-29 18:18:33 -07002556const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2557 int32_t x, int32_t y) {
2558 size_t numVirtualKeys = mLocked.virtualKeys.size();
2559 for (size_t i = 0; i < numVirtualKeys; i++) {
2560 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002561
2562#if DEBUG_VIRTUAL_KEYS
2563 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2564 "left=%d, top=%d, right=%d, bottom=%d",
2565 x, y,
2566 virtualKey.keyCode, virtualKey.scanCode,
2567 virtualKey.hitLeft, virtualKey.hitTop,
2568 virtualKey.hitRight, virtualKey.hitBottom);
2569#endif
2570
2571 if (virtualKey.isHit(x, y)) {
2572 return & virtualKey;
2573 }
2574 }
2575
2576 return NULL;
2577}
2578
2579void TouchInputMapper::calculatePointerIds() {
2580 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2581 uint32_t lastPointerCount = mLastTouch.pointerCount;
2582
2583 if (currentPointerCount == 0) {
2584 // No pointers to assign.
2585 mCurrentTouch.idBits.clear();
2586 } else if (lastPointerCount == 0) {
2587 // All pointers are new.
2588 mCurrentTouch.idBits.clear();
2589 for (uint32_t i = 0; i < currentPointerCount; i++) {
2590 mCurrentTouch.pointers[i].id = i;
2591 mCurrentTouch.idToIndex[i] = i;
2592 mCurrentTouch.idBits.markBit(i);
2593 }
2594 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2595 // Only one pointer and no change in count so it must have the same id as before.
2596 uint32_t id = mLastTouch.pointers[0].id;
2597 mCurrentTouch.pointers[0].id = id;
2598 mCurrentTouch.idToIndex[id] = 0;
2599 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2600 } else {
2601 // General case.
2602 // We build a heap of squared euclidean distances between current and last pointers
2603 // associated with the current and last pointer indices. Then, we find the best
2604 // match (by distance) for each current pointer.
2605 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2606
2607 uint32_t heapSize = 0;
2608 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2609 currentPointerIndex++) {
2610 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2611 lastPointerIndex++) {
2612 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2613 - mLastTouch.pointers[lastPointerIndex].x;
2614 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2615 - mLastTouch.pointers[lastPointerIndex].y;
2616
2617 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2618
2619 // Insert new element into the heap (sift up).
2620 heap[heapSize].currentPointerIndex = currentPointerIndex;
2621 heap[heapSize].lastPointerIndex = lastPointerIndex;
2622 heap[heapSize].distance = distance;
2623 heapSize += 1;
2624 }
2625 }
2626
2627 // Heapify
2628 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2629 startIndex -= 1;
2630 for (uint32_t parentIndex = startIndex; ;) {
2631 uint32_t childIndex = parentIndex * 2 + 1;
2632 if (childIndex >= heapSize) {
2633 break;
2634 }
2635
2636 if (childIndex + 1 < heapSize
2637 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2638 childIndex += 1;
2639 }
2640
2641 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2642 break;
2643 }
2644
2645 swap(heap[parentIndex], heap[childIndex]);
2646 parentIndex = childIndex;
2647 }
2648 }
2649
2650#if DEBUG_POINTER_ASSIGNMENT
2651 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2652 for (size_t i = 0; i < heapSize; i++) {
2653 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2654 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2655 heap[i].distance);
2656 }
2657#endif
2658
2659 // Pull matches out by increasing order of distance.
2660 // To avoid reassigning pointers that have already been matched, the loop keeps track
2661 // of which last and current pointers have been matched using the matchedXXXBits variables.
2662 // It also tracks the used pointer id bits.
2663 BitSet32 matchedLastBits(0);
2664 BitSet32 matchedCurrentBits(0);
2665 BitSet32 usedIdBits(0);
2666 bool first = true;
2667 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2668 for (;;) {
2669 if (first) {
2670 // The first time through the loop, we just consume the root element of
2671 // the heap (the one with smallest distance).
2672 first = false;
2673 } else {
2674 // Previous iterations consumed the root element of the heap.
2675 // Pop root element off of the heap (sift down).
2676 heapSize -= 1;
2677 assert(heapSize > 0);
2678
2679 // Sift down.
2680 heap[0] = heap[heapSize];
2681 for (uint32_t parentIndex = 0; ;) {
2682 uint32_t childIndex = parentIndex * 2 + 1;
2683 if (childIndex >= heapSize) {
2684 break;
2685 }
2686
2687 if (childIndex + 1 < heapSize
2688 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2689 childIndex += 1;
2690 }
2691
2692 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2693 break;
2694 }
2695
2696 swap(heap[parentIndex], heap[childIndex]);
2697 parentIndex = childIndex;
2698 }
2699
2700#if DEBUG_POINTER_ASSIGNMENT
2701 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2702 for (size_t i = 0; i < heapSize; i++) {
2703 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2704 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2705 heap[i].distance);
2706 }
2707#endif
2708 }
2709
2710 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2711 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2712
2713 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2714 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2715
2716 matchedCurrentBits.markBit(currentPointerIndex);
2717 matchedLastBits.markBit(lastPointerIndex);
2718
2719 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2720 mCurrentTouch.pointers[currentPointerIndex].id = id;
2721 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2722 usedIdBits.markBit(id);
2723
2724#if DEBUG_POINTER_ASSIGNMENT
2725 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2726 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2727#endif
2728 break;
2729 }
2730 }
2731
2732 // Assign fresh ids to new pointers.
2733 if (currentPointerCount > lastPointerCount) {
2734 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2735 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2736 uint32_t id = usedIdBits.firstUnmarkedBit();
2737
2738 mCurrentTouch.pointers[currentPointerIndex].id = id;
2739 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2740 usedIdBits.markBit(id);
2741
2742#if DEBUG_POINTER_ASSIGNMENT
2743 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2744 currentPointerIndex, id);
2745#endif
2746
2747 if (--i == 0) break; // done
2748 matchedCurrentBits.markBit(currentPointerIndex);
2749 }
2750 }
2751
2752 // Fix id bits.
2753 mCurrentTouch.idBits = usedIdBits;
2754 }
2755}
2756
2757/* Special hack for devices that have bad screen data: if one of the
2758 * points has moved more than a screen height from the last position,
2759 * then drop it. */
2760bool TouchInputMapper::applyBadTouchFilter() {
2761 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002762 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002763 return false;
2764 }
2765
2766 uint32_t pointerCount = mCurrentTouch.pointerCount;
2767
2768 // Nothing to do if there are no points.
2769 if (pointerCount == 0) {
2770 return false;
2771 }
2772
2773 // Don't do anything if a finger is going down or up. We run
2774 // here before assigning pointer IDs, so there isn't a good
2775 // way to do per-finger matching.
2776 if (pointerCount != mLastTouch.pointerCount) {
2777 return false;
2778 }
2779
2780 // We consider a single movement across more than a 7/16 of
2781 // the long size of the screen to be bad. This was a magic value
2782 // determined by looking at the maximum distance it is feasible
2783 // to actually move in one sample.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002784 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Browne57e8952010-07-23 21:28:06 -07002785
2786 // XXX The original code in InputDevice.java included commented out
2787 // code for testing the X axis. Note that when we drop a point
2788 // we don't actually restore the old X either. Strange.
2789 // The old code also tries to track when bad points were previously
2790 // detected but it turns out that due to the placement of a "break"
2791 // at the end of the loop, we never set mDroppedBadPoint to true
2792 // so it is effectively dead code.
2793 // Need to figure out if the old code is busted or just overcomplicated
2794 // but working as intended.
2795
2796 // Look through all new points and see if any are farther than
2797 // acceptable from all previous points.
2798 for (uint32_t i = pointerCount; i-- > 0; ) {
2799 int32_t y = mCurrentTouch.pointers[i].y;
2800 int32_t closestY = INT_MAX;
2801 int32_t closestDeltaY = 0;
2802
2803#if DEBUG_HACKS
2804 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2805#endif
2806
2807 for (uint32_t j = pointerCount; j-- > 0; ) {
2808 int32_t lastY = mLastTouch.pointers[j].y;
2809 int32_t deltaY = abs(y - lastY);
2810
2811#if DEBUG_HACKS
2812 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2813 j, lastY, deltaY);
2814#endif
2815
2816 if (deltaY < maxDeltaY) {
2817 goto SkipSufficientlyClosePoint;
2818 }
2819 if (deltaY < closestDeltaY) {
2820 closestDeltaY = deltaY;
2821 closestY = lastY;
2822 }
2823 }
2824
2825 // Must not have found a close enough match.
2826#if DEBUG_HACKS
2827 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2828 i, y, closestY, closestDeltaY, maxDeltaY);
2829#endif
2830
2831 mCurrentTouch.pointers[i].y = closestY;
2832 return true; // XXX original code only corrects one point
2833
2834 SkipSufficientlyClosePoint: ;
2835 }
2836
2837 // No change.
2838 return false;
2839}
2840
2841/* Special hack for devices that have bad screen data: drop points where
2842 * the coordinate value for one axis has jumped to the other pointer's location.
2843 */
2844bool TouchInputMapper::applyJumpyTouchFilter() {
2845 // This hack requires valid axis parameters.
Jeff Brown38a7fab2010-08-30 03:02:23 -07002846 if (! mRawAxes.y.valid) {
Jeff Browne57e8952010-07-23 21:28:06 -07002847 return false;
2848 }
2849
2850 uint32_t pointerCount = mCurrentTouch.pointerCount;
2851 if (mLastTouch.pointerCount != pointerCount) {
2852#if DEBUG_HACKS
2853 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2854 mLastTouch.pointerCount, pointerCount);
2855 for (uint32_t i = 0; i < pointerCount; i++) {
2856 LOGD(" Pointer %d (%d, %d)", i,
2857 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2858 }
2859#endif
2860
2861 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2862 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2863 // Just drop the first few events going from 1 to 2 pointers.
2864 // They're bad often enough that they're not worth considering.
2865 mCurrentTouch.pointerCount = 1;
2866 mJumpyTouchFilter.jumpyPointsDropped += 1;
2867
2868#if DEBUG_HACKS
2869 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2870#endif
2871 return true;
2872 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2873 // The event when we go from 2 -> 1 tends to be messed up too
2874 mCurrentTouch.pointerCount = 2;
2875 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2876 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2877 mJumpyTouchFilter.jumpyPointsDropped += 1;
2878
2879#if DEBUG_HACKS
2880 for (int32_t i = 0; i < 2; i++) {
2881 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2882 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2883 }
2884#endif
2885 return true;
2886 }
2887 }
2888 // Reset jumpy points dropped on other transitions or if limit exceeded.
2889 mJumpyTouchFilter.jumpyPointsDropped = 0;
2890
2891#if DEBUG_HACKS
2892 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2893#endif
2894 return false;
2895 }
2896
2897 // We have the same number of pointers as last time.
2898 // A 'jumpy' point is one where the coordinate value for one axis
2899 // has jumped to the other pointer's location. No need to do anything
2900 // else if we only have one pointer.
2901 if (pointerCount < 2) {
2902 return false;
2903 }
2904
2905 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07002906 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Browne57e8952010-07-23 21:28:06 -07002907
2908 // We only replace the single worst jumpy point as characterized by pointer distance
2909 // in a single axis.
2910 int32_t badPointerIndex = -1;
2911 int32_t badPointerReplacementIndex = -1;
2912 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2913
2914 for (uint32_t i = pointerCount; i-- > 0; ) {
2915 int32_t x = mCurrentTouch.pointers[i].x;
2916 int32_t y = mCurrentTouch.pointers[i].y;
2917
2918#if DEBUG_HACKS
2919 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2920#endif
2921
2922 // Check if a touch point is too close to another's coordinates
2923 bool dropX = false, dropY = false;
2924 for (uint32_t j = 0; j < pointerCount; j++) {
2925 if (i == j) {
2926 continue;
2927 }
2928
2929 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2930 dropX = true;
2931 break;
2932 }
2933
2934 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2935 dropY = true;
2936 break;
2937 }
2938 }
2939 if (! dropX && ! dropY) {
2940 continue; // not jumpy
2941 }
2942
2943 // Find a replacement candidate by comparing with older points on the
2944 // complementary (non-jumpy) axis.
2945 int32_t distance = INT_MIN; // distance to be corrected
2946 int32_t replacementIndex = -1;
2947
2948 if (dropX) {
2949 // X looks too close. Find an older replacement point with a close Y.
2950 int32_t smallestDeltaY = INT_MAX;
2951 for (uint32_t j = 0; j < pointerCount; j++) {
2952 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2953 if (deltaY < smallestDeltaY) {
2954 smallestDeltaY = deltaY;
2955 replacementIndex = j;
2956 }
2957 }
2958 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2959 } else {
2960 // Y looks too close. Find an older replacement point with a close X.
2961 int32_t smallestDeltaX = INT_MAX;
2962 for (uint32_t j = 0; j < pointerCount; j++) {
2963 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2964 if (deltaX < smallestDeltaX) {
2965 smallestDeltaX = deltaX;
2966 replacementIndex = j;
2967 }
2968 }
2969 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2970 }
2971
2972 // If replacing this pointer would correct a worse error than the previous ones
2973 // considered, then use this replacement instead.
2974 if (distance > badPointerDistance) {
2975 badPointerIndex = i;
2976 badPointerReplacementIndex = replacementIndex;
2977 badPointerDistance = distance;
2978 }
2979 }
2980
2981 // Correct the jumpy pointer if one was found.
2982 if (badPointerIndex >= 0) {
2983#if DEBUG_HACKS
2984 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2985 badPointerIndex,
2986 mLastTouch.pointers[badPointerReplacementIndex].x,
2987 mLastTouch.pointers[badPointerReplacementIndex].y);
2988#endif
2989
2990 mCurrentTouch.pointers[badPointerIndex].x =
2991 mLastTouch.pointers[badPointerReplacementIndex].x;
2992 mCurrentTouch.pointers[badPointerIndex].y =
2993 mLastTouch.pointers[badPointerReplacementIndex].y;
2994 mJumpyTouchFilter.jumpyPointsDropped += 1;
2995 return true;
2996 }
2997 }
2998
2999 mJumpyTouchFilter.jumpyPointsDropped = 0;
3000 return false;
3001}
3002
3003/* Special hack for devices that have bad screen data: aggregate and
3004 * compute averages of the coordinate data, to reduce the amount of
3005 * jitter seen by applications. */
3006void TouchInputMapper::applyAveragingTouchFilter() {
3007 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3008 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3009 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3010 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003011 int32_t pressure;
3012 switch (mCalibration.pressureSource) {
3013 case Calibration::PRESSURE_SOURCE_PRESSURE:
3014 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3015 break;
3016 case Calibration::PRESSURE_SOURCE_TOUCH:
3017 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3018 break;
3019 default:
3020 pressure = 1;
3021 break;
3022 }
Jeff Browne57e8952010-07-23 21:28:06 -07003023
3024 if (mLastTouch.idBits.hasBit(id)) {
3025 // Pointer was down before and is still down now.
3026 // Compute average over history trace.
3027 uint32_t start = mAveragingTouchFilter.historyStart[id];
3028 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3029
3030 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3031 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3032 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3033
3034#if DEBUG_HACKS
3035 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3036 id, distance);
3037#endif
3038
3039 if (distance < AVERAGING_DISTANCE_LIMIT) {
3040 // Increment end index in preparation for recording new historical data.
3041 end += 1;
3042 if (end > AVERAGING_HISTORY_SIZE) {
3043 end = 0;
3044 }
3045
3046 // If the end index has looped back to the start index then we have filled
3047 // the historical trace up to the desired size so we drop the historical
3048 // data at the start of the trace.
3049 if (end == start) {
3050 start += 1;
3051 if (start > AVERAGING_HISTORY_SIZE) {
3052 start = 0;
3053 }
3054 }
3055
3056 // Add the raw data to the historical trace.
3057 mAveragingTouchFilter.historyStart[id] = start;
3058 mAveragingTouchFilter.historyEnd[id] = end;
3059 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3060 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3061 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3062
3063 // Average over all historical positions in the trace by total pressure.
3064 int32_t averagedX = 0;
3065 int32_t averagedY = 0;
3066 int32_t totalPressure = 0;
3067 for (;;) {
3068 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3069 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3070 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3071 .pointers[id].pressure;
3072
3073 averagedX += historicalX * historicalPressure;
3074 averagedY += historicalY * historicalPressure;
3075 totalPressure += historicalPressure;
3076
3077 if (start == end) {
3078 break;
3079 }
3080
3081 start += 1;
3082 if (start > AVERAGING_HISTORY_SIZE) {
3083 start = 0;
3084 }
3085 }
3086
Jeff Brown38a7fab2010-08-30 03:02:23 -07003087 if (totalPressure != 0) {
3088 averagedX /= totalPressure;
3089 averagedY /= totalPressure;
Jeff Browne57e8952010-07-23 21:28:06 -07003090
3091#if DEBUG_HACKS
Jeff Brown38a7fab2010-08-30 03:02:23 -07003092 LOGD("AveragingTouchFilter: Pointer id %d - "
3093 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3094 averagedX, averagedY);
Jeff Browne57e8952010-07-23 21:28:06 -07003095#endif
3096
Jeff Brown38a7fab2010-08-30 03:02:23 -07003097 mCurrentTouch.pointers[currentIndex].x = averagedX;
3098 mCurrentTouch.pointers[currentIndex].y = averagedY;
3099 }
Jeff Browne57e8952010-07-23 21:28:06 -07003100 } else {
3101#if DEBUG_HACKS
3102 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3103#endif
3104 }
3105 } else {
3106#if DEBUG_HACKS
3107 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3108#endif
3109 }
3110
3111 // Reset pointer history.
3112 mAveragingTouchFilter.historyStart[id] = 0;
3113 mAveragingTouchFilter.historyEnd[id] = 0;
3114 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3115 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3116 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3117 }
3118}
3119
3120int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003121 { // acquire lock
3122 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003123
Jeff Brownb51719b2010-07-29 18:18:33 -07003124 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003125 return AKEY_STATE_VIRTUAL;
3126 }
3127
Jeff Brownb51719b2010-07-29 18:18:33 -07003128 size_t numVirtualKeys = mLocked.virtualKeys.size();
3129 for (size_t i = 0; i < numVirtualKeys; i++) {
3130 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003131 if (virtualKey.keyCode == keyCode) {
3132 return AKEY_STATE_UP;
3133 }
3134 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003135 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003136
3137 return AKEY_STATE_UNKNOWN;
3138}
3139
3140int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003141 { // acquire lock
3142 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003143
Jeff Brownb51719b2010-07-29 18:18:33 -07003144 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07003145 return AKEY_STATE_VIRTUAL;
3146 }
3147
Jeff Brownb51719b2010-07-29 18:18:33 -07003148 size_t numVirtualKeys = mLocked.virtualKeys.size();
3149 for (size_t i = 0; i < numVirtualKeys; i++) {
3150 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003151 if (virtualKey.scanCode == scanCode) {
3152 return AKEY_STATE_UP;
3153 }
3154 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003155 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003156
3157 return AKEY_STATE_UNKNOWN;
3158}
3159
3160bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3161 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07003162 { // acquire lock
3163 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07003164
Jeff Brownb51719b2010-07-29 18:18:33 -07003165 size_t numVirtualKeys = mLocked.virtualKeys.size();
3166 for (size_t i = 0; i < numVirtualKeys; i++) {
3167 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07003168
3169 for (size_t i = 0; i < numCodes; i++) {
3170 if (virtualKey.keyCode == keyCodes[i]) {
3171 outFlags[i] = 1;
3172 }
3173 }
3174 }
Jeff Brownb51719b2010-07-29 18:18:33 -07003175 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07003176
3177 return true;
3178}
3179
3180
3181// --- SingleTouchInputMapper ---
3182
3183SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3184 TouchInputMapper(device, associatedDisplayId) {
3185 initialize();
3186}
3187
3188SingleTouchInputMapper::~SingleTouchInputMapper() {
3189}
3190
3191void SingleTouchInputMapper::initialize() {
3192 mAccumulator.clear();
3193
3194 mDown = false;
3195 mX = 0;
3196 mY = 0;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003197 mPressure = 0; // default to 0 for devices that don't report pressure
3198 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Browne57e8952010-07-23 21:28:06 -07003199}
3200
3201void SingleTouchInputMapper::reset() {
3202 TouchInputMapper::reset();
3203
Jeff Browne57e8952010-07-23 21:28:06 -07003204 initialize();
3205 }
3206
3207void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3208 switch (rawEvent->type) {
3209 case EV_KEY:
3210 switch (rawEvent->scanCode) {
3211 case BTN_TOUCH:
3212 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3213 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003214 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3215 // not have received valid position information yet. This logic assumes that
3216 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07003217 break;
3218 }
3219 break;
3220
3221 case EV_ABS:
3222 switch (rawEvent->scanCode) {
3223 case ABS_X:
3224 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3225 mAccumulator.absX = rawEvent->value;
3226 break;
3227 case ABS_Y:
3228 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3229 mAccumulator.absY = rawEvent->value;
3230 break;
3231 case ABS_PRESSURE:
3232 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3233 mAccumulator.absPressure = rawEvent->value;
3234 break;
3235 case ABS_TOOL_WIDTH:
3236 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3237 mAccumulator.absToolWidth = rawEvent->value;
3238 break;
3239 }
3240 break;
3241
3242 case EV_SYN:
3243 switch (rawEvent->scanCode) {
3244 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003245 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003246 break;
3247 }
3248 break;
3249 }
3250}
3251
3252void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07003253 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07003254 if (fields == 0) {
3255 return; // no new state changes, so nothing to do
3256 }
Jeff Browne57e8952010-07-23 21:28:06 -07003257
3258 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3259 mDown = mAccumulator.btnTouch;
3260 }
3261
3262 if (fields & Accumulator::FIELD_ABS_X) {
3263 mX = mAccumulator.absX;
3264 }
3265
3266 if (fields & Accumulator::FIELD_ABS_Y) {
3267 mY = mAccumulator.absY;
3268 }
3269
3270 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3271 mPressure = mAccumulator.absPressure;
3272 }
3273
3274 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003275 mToolWidth = mAccumulator.absToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003276 }
3277
3278 mCurrentTouch.clear();
3279
3280 if (mDown) {
3281 mCurrentTouch.pointerCount = 1;
3282 mCurrentTouch.pointers[0].id = 0;
3283 mCurrentTouch.pointers[0].x = mX;
3284 mCurrentTouch.pointers[0].y = mY;
3285 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003286 mCurrentTouch.pointers[0].touchMajor = 0;
3287 mCurrentTouch.pointers[0].touchMinor = 0;
3288 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3289 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Browne57e8952010-07-23 21:28:06 -07003290 mCurrentTouch.pointers[0].orientation = 0;
3291 mCurrentTouch.idToIndex[0] = 0;
3292 mCurrentTouch.idBits.markBit(0);
3293 }
3294
3295 syncTouch(when, true);
Jeff Brownd64c8552010-08-17 20:38:35 -07003296
3297 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07003298}
3299
Jeff Brown38a7fab2010-08-30 03:02:23 -07003300void SingleTouchInputMapper::configureRawAxes() {
3301 TouchInputMapper::configureRawAxes();
Jeff Browne57e8952010-07-23 21:28:06 -07003302
Jeff Brown38a7fab2010-08-30 03:02:23 -07003303 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3304 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3305 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3306 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Browne57e8952010-07-23 21:28:06 -07003307}
3308
3309
3310// --- MultiTouchInputMapper ---
3311
3312MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
3313 TouchInputMapper(device, associatedDisplayId) {
3314 initialize();
3315}
3316
3317MultiTouchInputMapper::~MultiTouchInputMapper() {
3318}
3319
3320void MultiTouchInputMapper::initialize() {
3321 mAccumulator.clear();
3322}
3323
3324void MultiTouchInputMapper::reset() {
3325 TouchInputMapper::reset();
3326
Jeff Browne57e8952010-07-23 21:28:06 -07003327 initialize();
3328}
3329
3330void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3331 switch (rawEvent->type) {
3332 case EV_ABS: {
3333 uint32_t pointerIndex = mAccumulator.pointerCount;
3334 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3335
3336 switch (rawEvent->scanCode) {
3337 case ABS_MT_POSITION_X:
3338 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3339 pointer->absMTPositionX = rawEvent->value;
3340 break;
3341 case ABS_MT_POSITION_Y:
3342 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3343 pointer->absMTPositionY = rawEvent->value;
3344 break;
3345 case ABS_MT_TOUCH_MAJOR:
3346 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3347 pointer->absMTTouchMajor = rawEvent->value;
3348 break;
3349 case ABS_MT_TOUCH_MINOR:
3350 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3351 pointer->absMTTouchMinor = rawEvent->value;
3352 break;
3353 case ABS_MT_WIDTH_MAJOR:
3354 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3355 pointer->absMTWidthMajor = rawEvent->value;
3356 break;
3357 case ABS_MT_WIDTH_MINOR:
3358 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3359 pointer->absMTWidthMinor = rawEvent->value;
3360 break;
3361 case ABS_MT_ORIENTATION:
3362 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3363 pointer->absMTOrientation = rawEvent->value;
3364 break;
3365 case ABS_MT_TRACKING_ID:
3366 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3367 pointer->absMTTrackingId = rawEvent->value;
3368 break;
Jeff Brown38a7fab2010-08-30 03:02:23 -07003369 case ABS_MT_PRESSURE:
3370 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3371 pointer->absMTPressure = rawEvent->value;
3372 break;
Jeff Browne57e8952010-07-23 21:28:06 -07003373 }
3374 break;
3375 }
3376
3377 case EV_SYN:
3378 switch (rawEvent->scanCode) {
3379 case SYN_MT_REPORT: {
3380 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3381 uint32_t pointerIndex = mAccumulator.pointerCount;
3382
3383 if (mAccumulator.pointers[pointerIndex].fields) {
3384 if (pointerIndex == MAX_POINTERS) {
3385 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3386 MAX_POINTERS);
3387 } else {
3388 pointerIndex += 1;
3389 mAccumulator.pointerCount = pointerIndex;
3390 }
3391 }
3392
3393 mAccumulator.pointers[pointerIndex].clear();
3394 break;
3395 }
3396
3397 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07003398 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07003399 break;
3400 }
3401 break;
3402 }
3403}
3404
3405void MultiTouchInputMapper::sync(nsecs_t when) {
3406 static const uint32_t REQUIRED_FIELDS =
Jeff Brown38a7fab2010-08-30 03:02:23 -07003407 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07003408
Jeff Browne57e8952010-07-23 21:28:06 -07003409 uint32_t inCount = mAccumulator.pointerCount;
3410 uint32_t outCount = 0;
3411 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07003412
Jeff Browne57e8952010-07-23 21:28:06 -07003413 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003414
Jeff Browne57e8952010-07-23 21:28:06 -07003415 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003416 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3417 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07003418
Jeff Browne57e8952010-07-23 21:28:06 -07003419 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003420 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3421 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07003422 continue;
3423 }
3424
Jeff Brownd64c8552010-08-17 20:38:35 -07003425 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3426 outPointer.x = inPointer.absMTPositionX;
3427 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07003428
Jeff Brown38a7fab2010-08-30 03:02:23 -07003429 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3430 if (inPointer.absMTPressure <= 0) {
Jeff Brown3c3cc622010-10-20 15:33:38 -07003431 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3432 // a pointer going up. Drop this finger.
Jeff Brownd64c8552010-08-17 20:38:35 -07003433 continue;
3434 }
Jeff Brown38a7fab2010-08-30 03:02:23 -07003435 outPointer.pressure = inPointer.absMTPressure;
3436 } else {
3437 // Default pressure to 0 if absent.
3438 outPointer.pressure = 0;
3439 }
3440
3441 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3442 if (inPointer.absMTTouchMajor <= 0) {
3443 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3444 // a pointer going up. Drop this finger.
3445 continue;
3446 }
Jeff Brownd64c8552010-08-17 20:38:35 -07003447 outPointer.touchMajor = inPointer.absMTTouchMajor;
3448 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003449 // Default touch area to 0 if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003450 outPointer.touchMajor = 0;
3451 }
Jeff Browne839a582010-04-22 18:58:52 -07003452
Jeff Brownd64c8552010-08-17 20:38:35 -07003453 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3454 outPointer.touchMinor = inPointer.absMTTouchMinor;
3455 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003456 // Assume touch area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003457 outPointer.touchMinor = outPointer.touchMajor;
3458 }
Jeff Browne839a582010-04-22 18:58:52 -07003459
Jeff Brownd64c8552010-08-17 20:38:35 -07003460 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3461 outPointer.toolMajor = inPointer.absMTWidthMajor;
3462 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003463 // Default tool area to 0 if absent.
3464 outPointer.toolMajor = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07003465 }
Jeff Browne839a582010-04-22 18:58:52 -07003466
Jeff Brownd64c8552010-08-17 20:38:35 -07003467 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3468 outPointer.toolMinor = inPointer.absMTWidthMinor;
3469 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003470 // Assume tool area is circular.
Jeff Brownd64c8552010-08-17 20:38:35 -07003471 outPointer.toolMinor = outPointer.toolMajor;
3472 }
3473
3474 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3475 outPointer.orientation = inPointer.absMTOrientation;
3476 } else {
Jeff Brown38a7fab2010-08-30 03:02:23 -07003477 // Default orientation to vertical if absent.
Jeff Brownd64c8552010-08-17 20:38:35 -07003478 outPointer.orientation = 0;
3479 }
3480
Jeff Brown38a7fab2010-08-30 03:02:23 -07003481 // Assign pointer id using tracking id if available.
Jeff Browne57e8952010-07-23 21:28:06 -07003482 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07003483 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3484 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07003485
Jeff Browne57e8952010-07-23 21:28:06 -07003486 if (id > MAX_POINTER_ID) {
3487#if DEBUG_POINTERS
3488 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brownd1b0a2b2010-09-26 22:20:12 -07003489 "it is larger than max supported id %d",
Jeff Browne57e8952010-07-23 21:28:06 -07003490 id, MAX_POINTER_ID);
3491#endif
3492 havePointerIds = false;
3493 }
3494 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07003495 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07003496 mCurrentTouch.idToIndex[id] = outCount;
3497 mCurrentTouch.idBits.markBit(id);
3498 }
3499 } else {
3500 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07003501 }
3502 }
Jeff Browne839a582010-04-22 18:58:52 -07003503
Jeff Browne57e8952010-07-23 21:28:06 -07003504 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07003505 }
3506
Jeff Browne57e8952010-07-23 21:28:06 -07003507 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07003508
Jeff Browne57e8952010-07-23 21:28:06 -07003509 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07003510
3511 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07003512}
3513
Jeff Brown38a7fab2010-08-30 03:02:23 -07003514void MultiTouchInputMapper::configureRawAxes() {
3515 TouchInputMapper::configureRawAxes();
Jeff Browne839a582010-04-22 18:58:52 -07003516
Jeff Brown38a7fab2010-08-30 03:02:23 -07003517 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3518 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3519 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3520 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3521 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3522 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3523 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3524 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07003525}
3526
Jeff Browne839a582010-04-22 18:58:52 -07003527
3528} // namespace android