blob: 56e29778ee93b22e6643e4c8fd340cfda7f692af [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070021
Jeff Brown5c225b12010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070032#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070033
34namespace android {
35
36// --- Static Functions ---
37
38template<typename T>
39inline static T abs(const T& value) {
40 return value < 0 ? - value : value;
41}
42
43template<typename T>
44inline static T min(const T& a, const T& b) {
45 return a < b ? a : b;
46}
47
Jeff Brown5c225b12010-06-16 01:53:36 -070048template<typename T>
49inline static void swap(T& a, T& b) {
50 T temp = a;
51 a = b;
52 b = temp;
53}
54
55
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070056int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
57 int32_t mask;
58 switch (keyCode) {
Jeff Brownfd0358292010-06-30 16:10:35 -070059 case AKEYCODE_ALT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070060 mask = AMETA_ALT_LEFT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070061 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070062 case AKEYCODE_ALT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070063 mask = AMETA_ALT_RIGHT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070064 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070065 case AKEYCODE_SHIFT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070066 mask = AMETA_SHIFT_LEFT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070067 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070068 case AKEYCODE_SHIFT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070069 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070070 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070071 case AKEYCODE_SYM:
Jeff Brownc5ed5912010-07-14 18:48:53 -070072 mask = AMETA_SYM_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070073 break;
74 default:
75 return oldMetaState;
76 }
77
78 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brownc5ed5912010-07-14 18:48:53 -070079 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070080
Jeff Brownc5ed5912010-07-14 18:48:53 -070081 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
82 newMetaState |= AMETA_ALT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070083 }
84
Jeff Brownc5ed5912010-07-14 18:48:53 -070085 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
86 newMetaState |= AMETA_SHIFT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070087 }
88
89 return newMetaState;
90}
91
92static const int32_t keyCodeRotationMap[][4] = {
93 // key codes enumerated counter-clockwise with the original (unrotated) key first
94 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -070095 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
96 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
97 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
98 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070099};
100static const int keyCodeRotationMapSize =
101 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
102
103int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700104 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700105 for (int i = 0; i < keyCodeRotationMapSize; i++) {
106 if (keyCode == keyCodeRotationMap[i][0]) {
107 return keyCodeRotationMap[i][orientation];
108 }
109 }
110 }
111 return keyCode;
112}
113
Jeff Brown6d0fec22010-07-23 21:28:06 -0700114static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
115 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
116}
117
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700118
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700119// --- InputReader ---
120
121InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700123 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700124 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
125 mGlobalMetaState(0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700126 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700127 updateGlobalMetaState();
128 updateInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700129}
130
131InputReader::~InputReader() {
132 for (size_t i = 0; i < mDevices.size(); i++) {
133 delete mDevices.valueAt(i);
134 }
135}
136
137void InputReader::loopOnce() {
138 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700139 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700140
141#if DEBUG_RAW_EVENTS
142 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
143 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
144 rawEvent.value);
145#endif
146
147 process(& rawEvent);
148}
149
150void InputReader::process(const RawEvent* rawEvent) {
151 switch (rawEvent->type) {
152 case EventHubInterface::DEVICE_ADDED:
Jeff Brown6d0fec22010-07-23 21:28:06 -0700153 addDevice(rawEvent->when, rawEvent->deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700154 break;
155
156 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown6d0fec22010-07-23 21:28:06 -0700157 removeDevice(rawEvent->when, rawEvent->deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700158 break;
159
Jeff Brown6d0fec22010-07-23 21:28:06 -0700160 default:
161 consumeEvent(rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700162 break;
163 }
164}
165
Jeff Brown6d0fec22010-07-23 21:28:06 -0700166void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
167 String8 name = mEventHub->getDeviceName(deviceId);
168 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
169
170 InputDevice* device = createDevice(deviceId, name, classes);
171 device->configure();
172
173 bool added = false;
174 { // acquire device registry writer lock
175 RWLock::AutoWLock _wl(mDeviceRegistryLock);
176
177 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
178 if (deviceIndex < 0) {
179 mDevices.add(deviceId, device);
180 added = true;
181 }
182 } // release device registry writer lock
183
184 if (! added) {
185 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
186 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700187 return;
188 }
189
Jeff Brown6d0fec22010-07-23 21:28:06 -0700190 if (device->isIgnored()) {
191 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)",
192 deviceId, name.string());
193 } else {
194 LOGI("Device added: id=0x%x, name=%s, sources=%08x",
195 deviceId, name.string(), device->getSources());
196 }
197
198 handleConfigurationChanged(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700199}
200
Jeff Brown6d0fec22010-07-23 21:28:06 -0700201void InputReader::removeDevice(nsecs_t when, int32_t deviceId) {
202 bool removed = false;
203 InputDevice* device = NULL;
204 { // acquire device registry writer lock
205 RWLock::AutoWLock _wl(mDeviceRegistryLock);
206
207 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
208 if (deviceIndex >= 0) {
209 device = mDevices.valueAt(deviceIndex);
210 mDevices.removeItemsAt(deviceIndex, 1);
211 removed = true;
212 }
213 } // release device registry writer lock
214
215 if (! removed) {
216 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 device->reset();
221
222 if (device->isIgnored()) {
223 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
224 device->getId(), device->getName().string());
225 } else {
226 LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
227 device->getId(), device->getName().string(), device->getSources());
228 }
229
230 delete device;
231
232 handleConfigurationChanged(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700233}
234
Jeff Brown6d0fec22010-07-23 21:28:06 -0700235InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
236 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700237
Jeff Brown6d0fec22010-07-23 21:28:06 -0700238 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700239
Jeff Brown6d0fec22010-07-23 21:28:06 -0700240 // Switch-like devices.
241 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
242 device->addMapper(new SwitchInputMapper(device));
243 }
244
245 // Keyboard-like devices.
246 uint32_t keyboardSources = 0;
247 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
248 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
249 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
250 }
251 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
252 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
253 }
254 if (classes & INPUT_DEVICE_CLASS_DPAD) {
255 keyboardSources |= AINPUT_SOURCE_DPAD;
256 }
257 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
258 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
259 }
260
261 if (keyboardSources != 0) {
262 device->addMapper(new KeyboardInputMapper(device,
263 associatedDisplayId, keyboardSources, keyboardType));
264 }
265
266 // Trackball-like devices.
267 if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
268 device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
269 }
270
271 // Touchscreen-like devices.
272 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
273 device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
274 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
275 device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
276 }
277
278 return device;
279}
280
281void InputReader::consumeEvent(const RawEvent* rawEvent) {
282 int32_t deviceId = rawEvent->deviceId;
283
284 { // acquire device registry reader lock
285 RWLock::AutoRLock _rl(mDeviceRegistryLock);
286
287 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
288 if (deviceIndex < 0) {
289 LOGW("Discarding event for unknown deviceId %d.", deviceId);
290 return;
291 }
292
293 InputDevice* device = mDevices.valueAt(deviceIndex);
294 if (device->isIgnored()) {
295 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
296 return;
297 }
298
299 device->process(rawEvent);
300 } // release device registry reader lock
301}
302
303void InputReader::handleConfigurationChanged(nsecs_t when) {
304 // Reset global meta state because it depends on the list of all configured devices.
305 updateGlobalMetaState();
306
307 // Update input configuration.
308 updateInputConfiguration();
309
310 // Enqueue configuration changed.
311 mDispatcher->notifyConfigurationChanged(when);
312}
313
314void InputReader::configureExcludedDevices() {
315 Vector<String8> excludedDeviceNames;
316 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
317
318 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
319 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
320 }
321}
322
323void InputReader::updateGlobalMetaState() {
324 { // acquire state lock
325 AutoMutex _l(mStateLock);
326
327 mGlobalMetaState = 0;
328
329 { // acquire device registry reader lock
330 RWLock::AutoRLock _rl(mDeviceRegistryLock);
331
332 for (size_t i = 0; i < mDevices.size(); i++) {
333 InputDevice* device = mDevices.valueAt(i);
334 mGlobalMetaState |= device->getMetaState();
335 }
336 } // release device registry reader lock
337 } // release state lock
338}
339
340int32_t InputReader::getGlobalMetaState() {
341 { // acquire state lock
342 AutoMutex _l(mStateLock);
343
344 return mGlobalMetaState;
345 } // release state lock
346}
347
348void InputReader::updateInputConfiguration() {
349 { // acquire state lock
350 AutoMutex _l(mStateLock);
351
352 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
353 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
354 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
355 { // acquire device registry reader lock
356 RWLock::AutoRLock _rl(mDeviceRegistryLock);
357
358 InputDeviceInfo deviceInfo;
359 for (size_t i = 0; i < mDevices.size(); i++) {
360 InputDevice* device = mDevices.valueAt(i);
361 device->getDeviceInfo(& deviceInfo);
362 uint32_t sources = deviceInfo.getSources();
363
364 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
365 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
366 }
367 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
368 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
369 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
370 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
371 }
372 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
373 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700374 }
375 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700377
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 mInputConfiguration.touchScreen = touchScreenConfig;
379 mInputConfiguration.keyboard = keyboardConfig;
380 mInputConfiguration.navigation = navigationConfig;
381 } // release state lock
382}
383
384void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
385 { // acquire state lock
386 AutoMutex _l(mStateLock);
387
388 *outConfiguration = mInputConfiguration;
389 } // release state lock
390}
391
392status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
393 { // acquire device registry reader lock
394 RWLock::AutoRLock _rl(mDeviceRegistryLock);
395
396 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
397 if (deviceIndex < 0) {
398 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700399 }
400
Jeff Brown6d0fec22010-07-23 21:28:06 -0700401 InputDevice* device = mDevices.valueAt(deviceIndex);
402 if (device->isIgnored()) {
403 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700404 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700405
406 device->getDeviceInfo(outDeviceInfo);
407 return OK;
408 } // release device registy reader lock
409}
410
411void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
412 outDeviceIds.clear();
413
414 { // acquire device registry reader lock
415 RWLock::AutoRLock _rl(mDeviceRegistryLock);
416
417 size_t numDevices = mDevices.size();
418 for (size_t i = 0; i < numDevices; i++) {
419 InputDevice* device = mDevices.valueAt(i);
420 if (! device->isIgnored()) {
421 outDeviceIds.add(device->getId());
422 }
423 }
424 } // release device registy reader lock
425}
426
427int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
428 int32_t keyCode) {
429 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
430}
431
432int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
433 int32_t scanCode) {
434 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
435}
436
437int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
438 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
439}
440
441int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
442 GetStateFunc getStateFunc) {
443 { // acquire device registry reader lock
444 RWLock::AutoRLock _rl(mDeviceRegistryLock);
445
446 int32_t result = AKEY_STATE_UNKNOWN;
447 if (deviceId >= 0) {
448 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
449 if (deviceIndex >= 0) {
450 InputDevice* device = mDevices.valueAt(deviceIndex);
451 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
452 result = (device->*getStateFunc)(sourceMask, code);
453 }
454 }
455 } else {
456 size_t numDevices = mDevices.size();
457 for (size_t i = 0; i < numDevices; i++) {
458 InputDevice* device = mDevices.valueAt(i);
459 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
460 result = (device->*getStateFunc)(sourceMask, code);
461 if (result >= AKEY_STATE_DOWN) {
462 return result;
463 }
464 }
465 }
466 }
467 return result;
468 } // release device registy reader lock
469}
470
471bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
472 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
473 memset(outFlags, 0, numCodes);
474 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
475}
476
477bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
478 const int32_t* keyCodes, uint8_t* outFlags) {
479 { // acquire device registry reader lock
480 RWLock::AutoRLock _rl(mDeviceRegistryLock);
481 bool result = false;
482 if (deviceId >= 0) {
483 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
484 if (deviceIndex >= 0) {
485 InputDevice* device = mDevices.valueAt(deviceIndex);
486 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
487 result = device->markSupportedKeyCodes(sourceMask,
488 numCodes, keyCodes, outFlags);
489 }
490 }
491 } else {
492 size_t numDevices = mDevices.size();
493 for (size_t i = 0; i < numDevices; i++) {
494 InputDevice* device = mDevices.valueAt(i);
495 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
496 result |= device->markSupportedKeyCodes(sourceMask,
497 numCodes, keyCodes, outFlags);
498 }
499 }
500 }
501 return result;
502 } // release device registy reader lock
503}
504
505
506// --- InputReaderThread ---
507
508InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
509 Thread(/*canCallJava*/ true), mReader(reader) {
510}
511
512InputReaderThread::~InputReaderThread() {
513}
514
515bool InputReaderThread::threadLoop() {
516 mReader->loopOnce();
517 return true;
518}
519
520
521// --- InputDevice ---
522
523InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
524 mContext(context), mId(id), mName(name), mSources(0) {
525}
526
527InputDevice::~InputDevice() {
528 size_t numMappers = mMappers.size();
529 for (size_t i = 0; i < numMappers; i++) {
530 delete mMappers[i];
531 }
532 mMappers.clear();
533}
534
535void InputDevice::addMapper(InputMapper* mapper) {
536 mMappers.add(mapper);
537}
538
539void InputDevice::configure() {
540 mSources = 0;
541
542 size_t numMappers = mMappers.size();
543 for (size_t i = 0; i < numMappers; i++) {
544 InputMapper* mapper = mMappers[i];
545 mapper->configure();
546 mSources |= mapper->getSources();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700547 }
548}
549
Jeff Brown6d0fec22010-07-23 21:28:06 -0700550void InputDevice::reset() {
551 size_t numMappers = mMappers.size();
552 for (size_t i = 0; i < numMappers; i++) {
553 InputMapper* mapper = mMappers[i];
554 mapper->reset();
555 }
556}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700557
Jeff Brown6d0fec22010-07-23 21:28:06 -0700558void InputDevice::process(const RawEvent* rawEvent) {
559 size_t numMappers = mMappers.size();
560 for (size_t i = 0; i < numMappers; i++) {
561 InputMapper* mapper = mMappers[i];
562 mapper->process(rawEvent);
563 }
564}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700565
Jeff Brown6d0fec22010-07-23 21:28:06 -0700566void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
567 outDeviceInfo->initialize(mId, mName);
568
569 size_t numMappers = mMappers.size();
570 for (size_t i = 0; i < numMappers; i++) {
571 InputMapper* mapper = mMappers[i];
572 mapper->populateDeviceInfo(outDeviceInfo);
573 }
574}
575
576int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
577 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
578}
579
580int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
581 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
582}
583
584int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
585 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
586}
587
588int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
589 int32_t result = AKEY_STATE_UNKNOWN;
590 size_t numMappers = mMappers.size();
591 for (size_t i = 0; i < numMappers; i++) {
592 InputMapper* mapper = mMappers[i];
593 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
594 result = (mapper->*getStateFunc)(sourceMask, code);
595 if (result >= AKEY_STATE_DOWN) {
596 return result;
597 }
598 }
599 }
600 return result;
601}
602
603bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
604 const int32_t* keyCodes, uint8_t* outFlags) {
605 bool result = false;
606 size_t numMappers = mMappers.size();
607 for (size_t i = 0; i < numMappers; i++) {
608 InputMapper* mapper = mMappers[i];
609 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
610 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
611 }
612 }
613 return result;
614}
615
616int32_t InputDevice::getMetaState() {
617 int32_t result = 0;
618 size_t numMappers = mMappers.size();
619 for (size_t i = 0; i < numMappers; i++) {
620 InputMapper* mapper = mMappers[i];
621 result |= mapper->getMetaState();
622 }
623 return result;
624}
625
626
627// --- InputMapper ---
628
629InputMapper::InputMapper(InputDevice* device) :
630 mDevice(device), mContext(device->getContext()) {
631}
632
633InputMapper::~InputMapper() {
634}
635
636void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
637 info->addSource(getSources());
638}
639
640void InputMapper::configure() {
641}
642
643void InputMapper::reset() {
644}
645
646int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
647 return AKEY_STATE_UNKNOWN;
648}
649
650int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
651 return AKEY_STATE_UNKNOWN;
652}
653
654int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
655 return AKEY_STATE_UNKNOWN;
656}
657
658bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
659 const int32_t* keyCodes, uint8_t* outFlags) {
660 return false;
661}
662
663int32_t InputMapper::getMetaState() {
664 return 0;
665}
666
667bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
668 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
669 getDispatcher()->notifyAppSwitchComing(when);
670 }
671
672 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
673}
674
675
676// --- SwitchInputMapper ---
677
678SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
679 InputMapper(device) {
680}
681
682SwitchInputMapper::~SwitchInputMapper() {
683}
684
685uint32_t SwitchInputMapper::getSources() {
686 return 0;
687}
688
689void SwitchInputMapper::process(const RawEvent* rawEvent) {
690 switch (rawEvent->type) {
691 case EV_SW:
692 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
693 break;
694 }
695}
696
697void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
698 uint32_t policyFlags = 0;
699 int32_t policyActions = getPolicy()->interceptSwitch(
700 when, switchCode, switchValue, policyFlags);
701
702 applyStandardPolicyActions(when, policyActions);
703}
704
705int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
706 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
707}
708
709
710// --- KeyboardInputMapper ---
711
712KeyboardInputMapper::KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId,
713 uint32_t sources, int32_t keyboardType) :
714 InputMapper(device), mAssociatedDisplayId(associatedDisplayId), mSources(sources),
715 mKeyboardType(keyboardType) {
716 initialize();
717}
718
719KeyboardInputMapper::~KeyboardInputMapper() {
720}
721
722void KeyboardInputMapper::initialize() {
723 mMetaState = AMETA_NONE;
724 mDownTime = 0;
725}
726
727uint32_t KeyboardInputMapper::getSources() {
728 return mSources;
729}
730
731void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
732 InputMapper::populateDeviceInfo(info);
733
734 info->setKeyboardType(mKeyboardType);
735}
736
737void KeyboardInputMapper::reset() {
738 // Synthesize key up event on reset if keys are currently down.
739 while (! mKeyDowns.isEmpty()) {
740 const KeyDown& keyDown = mKeyDowns.top();
741 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
742 processKey(when, false, keyDown.keyCode, keyDown.scanCode, 0);
743 }
744
745 InputMapper::reset();
746
747 // Reinitialize.
748 initialize();
749 getContext()->updateGlobalMetaState();
750}
751
752void KeyboardInputMapper::process(const RawEvent* rawEvent) {
753 switch (rawEvent->type) {
754 case EV_KEY: {
755 int32_t scanCode = rawEvent->scanCode;
756 if (isKeyboardOrGamepadKey(scanCode)) {
757 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
758 rawEvent->flags);
759 }
760 break;
761 }
762 }
763}
764
765bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
766 return scanCode < BTN_MOUSE
767 || scanCode >= KEY_OK
768 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
769}
770
771void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
772 uint32_t policyFlags) {
773 if (down) {
774 // Rotate key codes according to orientation.
775 if (mAssociatedDisplayId >= 0) {
776 int32_t orientation;
777 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
778 return;
779 }
780
781 keyCode = rotateKeyCode(keyCode, orientation);
782 }
783
784 // Add key down.
785 ssize_t keyDownIndex = findKeyDown(scanCode);
786 if (keyDownIndex >= 0) {
787 // key repeat, be sure to use same keycode as before in case of rotation
788 keyCode = mKeyDowns.top().keyCode;
789 } else {
790 // key down
791 mKeyDowns.push();
792 KeyDown& keyDown = mKeyDowns.editTop();
793 keyDown.keyCode = keyCode;
794 keyDown.scanCode = scanCode;
795 }
796 } else {
797 // Remove key down.
798 ssize_t keyDownIndex = findKeyDown(scanCode);
799 if (keyDownIndex >= 0) {
800 // key up, be sure to use same keycode as before in case of rotation
801 keyCode = mKeyDowns.top().keyCode;
802 mKeyDowns.removeAt(size_t(keyDownIndex));
803 } else {
804 // key was not actually down
805 LOGI("Dropping key up from device %s because the key was not down. "
806 "keyCode=%d, scanCode=%d",
807 getDeviceName().string(), keyCode, scanCode);
Jeff Brownfd0358292010-06-30 16:10:35 -0700808 return;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700809 }
Jeff Brownfd0358292010-06-30 16:10:35 -0700810 }
811
Jeff Brown6d0fec22010-07-23 21:28:06 -0700812 int32_t oldMetaState = mMetaState;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700813 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
814 if (oldMetaState != newMetaState) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700815 mMetaState = newMetaState;
816 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700817 }
818
Jeff Brown6d0fec22010-07-23 21:28:06 -0700819 /* Apply policy. */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700820
Jeff Brown6d0fec22010-07-23 21:28:06 -0700821 int32_t policyActions = getPolicy()->interceptKey(when,
822 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700823
Jeff Brown6d0fec22010-07-23 21:28:06 -0700824 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700825 return; // event dropped
826 }
827
Jeff Brown6d0fec22010-07-23 21:28:06 -0700828 /* Enqueue key event for dispatch. */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700829
830 int32_t keyEventAction;
831 if (down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700832 mDownTime = when;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700833 keyEventAction = AKEY_EVENT_ACTION_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700834 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700835 keyEventAction = AKEY_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700836 }
837
Jeff Brownc5ed5912010-07-14 18:48:53 -0700838 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700839 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700840 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700841 }
842
Jeff Brown6d0fec22010-07-23 21:28:06 -0700843 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700844 keyEventAction, keyEventFlags, keyCode, scanCode,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700845 mMetaState, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700846}
847
Jeff Brown6d0fec22010-07-23 21:28:06 -0700848ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
849 size_t n = mKeyDowns.size();
850 for (size_t i = 0; i < n; i++) {
851 if (mKeyDowns[i].scanCode == scanCode) {
852 return i;
853 }
854 }
855 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700856}
857
Jeff Brown6d0fec22010-07-23 21:28:06 -0700858int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
859 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
860}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700861
Jeff Brown6d0fec22010-07-23 21:28:06 -0700862int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
863 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
864}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700865
Jeff Brown6d0fec22010-07-23 21:28:06 -0700866bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
867 const int32_t* keyCodes, uint8_t* outFlags) {
868 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
869}
870
871int32_t KeyboardInputMapper::getMetaState() {
872 return mMetaState;
873}
874
875
876// --- TrackballInputMapper ---
877
878TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
879 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
880 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
881 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
882 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
883 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
884
885 initialize();
886}
887
888TrackballInputMapper::~TrackballInputMapper() {
889}
890
891uint32_t TrackballInputMapper::getSources() {
892 return AINPUT_SOURCE_TRACKBALL;
893}
894
895void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
896 InputMapper::populateDeviceInfo(info);
897
898 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
899 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
900}
901
902void TrackballInputMapper::initialize() {
903 mAccumulator.clear();
904
905 mDown = false;
906 mDownTime = 0;
907}
908
909void TrackballInputMapper::reset() {
910 // Synthesize trackball button up event on reset if trackball button is currently down.
911 if (mDown) {
912 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
913 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
914 mAccumulator.btnMouse = false;
915 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700916 }
917
Jeff Brown6d0fec22010-07-23 21:28:06 -0700918 InputMapper::reset();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700919
Jeff Brown6d0fec22010-07-23 21:28:06 -0700920 // Reinitialize.
921 initialize();
922}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700923
Jeff Brown6d0fec22010-07-23 21:28:06 -0700924void TrackballInputMapper::process(const RawEvent* rawEvent) {
925 switch (rawEvent->type) {
926 case EV_KEY:
927 switch (rawEvent->scanCode) {
928 case BTN_MOUSE:
929 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
930 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700931
Jeff Brown6d0fec22010-07-23 21:28:06 -0700932 sync(rawEvent->when);
933 mAccumulator.clear();
934 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700935 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700936 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700937
Jeff Brown6d0fec22010-07-23 21:28:06 -0700938 case EV_REL:
939 switch (rawEvent->scanCode) {
940 case REL_X:
941 mAccumulator.fields |= Accumulator::FIELD_REL_X;
942 mAccumulator.relX = rawEvent->value;
943 break;
944 case REL_Y:
945 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
946 mAccumulator.relY = rawEvent->value;
947 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700948 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700949 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700950
Jeff Brown6d0fec22010-07-23 21:28:06 -0700951 case EV_SYN:
952 switch (rawEvent->scanCode) {
953 case SYN_REPORT:
954 if (mAccumulator.isDirty()) {
955 sync(rawEvent->when);
956 mAccumulator.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700957 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700958 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700959 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700960 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700961 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700962}
963
Jeff Brown6d0fec22010-07-23 21:28:06 -0700964void TrackballInputMapper::sync(nsecs_t when) {
965 /* Get display properties so for rotation based on display orientation. */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700966
Jeff Brown6d0fec22010-07-23 21:28:06 -0700967 int32_t orientation;
968 if (mAssociatedDisplayId >= 0) {
969 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
970 return;
971 }
972 } else {
973 orientation = InputReaderPolicyInterface::ROTATION_0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700974 }
975
Jeff Brown6d0fec22010-07-23 21:28:06 -0700976 /* Update saved trackball state */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700977
Jeff Brown6d0fec22010-07-23 21:28:06 -0700978 uint32_t fields = mAccumulator.fields;
979 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700980
Jeff Brown6d0fec22010-07-23 21:28:06 -0700981 if (downChanged) {
982 if (mAccumulator.btnMouse) {
983 mDown = true;
984 mDownTime = when;
985 } else {
986 mDown = false;
987 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700988 }
989
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700990 /* Apply policy */
991
Jeff Brown6d0fec22010-07-23 21:28:06 -0700992 uint32_t policyFlags = 0;
993 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
994
995 if (! applyStandardPolicyActions(when, policyActions)) {
996 return; // event dropped
997 }
998
999 /* Enqueue motion event for dispatch. */
1000
1001 int32_t motionEventAction;
1002 if (downChanged) {
1003 motionEventAction = mDown ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1004 } else {
1005 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
1006 }
1007
1008 int32_t pointerId = 0;
1009 PointerCoords pointerCoords;
1010 pointerCoords.x = fields & Accumulator::FIELD_REL_X
1011 ? mAccumulator.relX * mXScale : 0;
1012 pointerCoords.y = fields & Accumulator::FIELD_REL_Y
1013 ? mAccumulator.relY * mYScale : 0;
1014 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
1015 pointerCoords.size = 0;
1016 pointerCoords.touchMajor = 0;
1017 pointerCoords.touchMinor = 0;
1018 pointerCoords.toolMajor = 0;
1019 pointerCoords.toolMinor = 0;
1020 pointerCoords.orientation = 0;
1021
1022 float temp;
1023 switch (orientation) {
1024 case InputReaderPolicyInterface::ROTATION_90:
1025 temp = pointerCoords.x;
1026 pointerCoords.x = pointerCoords.y;
1027 pointerCoords.y = - temp;
1028 break;
1029
1030 case InputReaderPolicyInterface::ROTATION_180:
1031 pointerCoords.x = - pointerCoords.x;
1032 pointerCoords.y = - pointerCoords.y;
1033 break;
1034
1035 case InputReaderPolicyInterface::ROTATION_270:
1036 temp = pointerCoords.x;
1037 pointerCoords.x = - pointerCoords.y;
1038 pointerCoords.y = temp;
1039 break;
1040 }
1041
1042 int32_t metaState = mContext->getGlobalMetaState();
1043 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
1044 motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1045 1, & pointerId, & pointerCoords, mXPrecision, mYPrecision, mDownTime);
1046}
1047
1048
1049// --- TouchInputMapper ---
1050
1051TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
1052 InputMapper(device), mAssociatedDisplayId(associatedDisplayId),
1053 mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) {
1054 initialize();
1055}
1056
1057TouchInputMapper::~TouchInputMapper() {
1058}
1059
1060uint32_t TouchInputMapper::getSources() {
1061 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1062}
1063
1064void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1065 InputMapper::populateDeviceInfo(info);
1066
1067 // FIXME: Should ensure the surface information is up to date so that orientation changes
1068 // are noticed immediately. Unfortunately we will need to add some extra locks here
1069 // to prevent race conditions.
1070 // configureSurface();
1071
1072 info->addMotionRange(AINPUT_MOTION_RANGE_X, mOrientedRanges.x);
1073 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mOrientedRanges.y);
1074 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, mOrientedRanges.pressure);
1075 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE, mOrientedRanges.size);
1076 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR, mOrientedRanges.touchMajor);
1077 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR, mOrientedRanges.touchMinor);
1078 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR, mOrientedRanges.toolMajor);
1079 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR, mOrientedRanges.toolMinor);
1080 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION, mOrientedRanges.orientation);
1081}
1082
1083void TouchInputMapper::initialize() {
1084 mLastTouch.clear();
1085 mDownTime = 0;
1086 mCurrentVirtualKey.down = false;
1087
1088 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1089 mAveragingTouchFilter.historyStart[i] = 0;
1090 mAveragingTouchFilter.historyEnd[i] = 0;
1091 }
1092
1093 mJumpyTouchFilter.jumpyPointsDropped = 0;
1094}
1095
1096void TouchInputMapper::configure() {
1097 InputMapper::configure();
1098
1099 // Configure basic parameters.
1100 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1101 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1102 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1103
1104 // Configure absolute axis information.
1105 configureAxes();
1106
1107 // Configure pressure factors.
1108 if (mAxes.pressure.valid) {
1109 mPressureOrigin = mAxes.pressure.minValue;
1110 mPressureScale = 1.0f / mAxes.pressure.getRange();
1111 } else {
1112 mPressureOrigin = 0;
1113 mPressureScale = 1.0f;
1114 }
1115
1116 mOrientedRanges.pressure.min = 0.0f;
1117 mOrientedRanges.pressure.max = 1.0f;
1118 mOrientedRanges.pressure.flat = 0.0f;
1119 mOrientedRanges.pressure.fuzz = mPressureScale;
1120
1121 // Configure size factors.
1122 if (mAxes.size.valid) {
1123 mSizeOrigin = mAxes.size.minValue;
1124 mSizeScale = 1.0f / mAxes.size.getRange();
1125 } else {
1126 mSizeOrigin = 0;
1127 mSizeScale = 1.0f;
1128 }
1129
1130 mOrientedRanges.size.min = 0.0f;
1131 mOrientedRanges.size.max = 1.0f;
1132 mOrientedRanges.size.flat = 0.0f;
1133 mOrientedRanges.size.fuzz = mSizeScale;
1134
1135 // Configure orientation factors.
1136 if (mAxes.orientation.valid && mAxes.orientation.maxValue > 0) {
1137 mOrientationScale = float(M_PI_2) / mAxes.orientation.maxValue;
1138 } else {
1139 mOrientationScale = 0.0f;
1140 }
1141
1142 mOrientedRanges.orientation.min = - M_PI_2;
1143 mOrientedRanges.orientation.max = M_PI_2;
1144 mOrientedRanges.orientation.flat = 0;
1145 mOrientedRanges.orientation.fuzz = mOrientationScale;
1146
1147 // Configure surface dimensions and orientation.
1148 configureSurface();
1149}
1150
1151void TouchInputMapper::configureAxes() {
1152 mAxes.x.valid = false;
1153 mAxes.y.valid = false;
1154 mAxes.pressure.valid = false;
1155 mAxes.size.valid = false;
1156 mAxes.touchMajor.valid = false;
1157 mAxes.touchMinor.valid = false;
1158 mAxes.toolMajor.valid = false;
1159 mAxes.toolMinor.valid = false;
1160 mAxes.orientation.valid = false;
1161}
1162
1163bool TouchInputMapper::configureSurface() {
1164 // Update orientation and dimensions if needed.
1165 int32_t orientation;
1166 int32_t width, height;
1167 if (mAssociatedDisplayId >= 0) {
1168 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1169 return false;
1170 }
1171 } else {
1172 orientation = InputReaderPolicyInterface::ROTATION_0;
1173 width = mAxes.x.getRange();
1174 height = mAxes.y.getRange();
1175 }
1176
1177 bool orientationChanged = mSurfaceOrientation != orientation;
1178 if (orientationChanged) {
1179 mSurfaceOrientation = orientation;
1180 }
1181
1182 bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height;
1183 if (sizeChanged) {
1184 mSurfaceWidth = width;
1185 mSurfaceHeight = height;
1186
1187 // Compute size-dependent translation and scaling factors and place virtual keys.
1188 if (mAxes.x.valid && mAxes.y.valid) {
1189 mXOrigin = mAxes.x.minValue;
1190 mYOrigin = mAxes.y.minValue;
1191
1192 LOGI("Device configured: id=0x%x, name=%s (display size was changed)",
1193 getDeviceId(), getDeviceName().string());
1194
1195 mXScale = float(width) / mAxes.x.getRange();
1196 mYScale = float(height) / mAxes.y.getRange();
1197 mXPrecision = 1.0f / mXScale;
1198 mYPrecision = 1.0f / mYScale;
1199
1200 configureVirtualKeys();
1201 } else {
1202 mXOrigin = 0;
1203 mYOrigin = 0;
1204 mXScale = 1.0f;
1205 mYScale = 1.0f;
1206 mXPrecision = 1.0f;
1207 mYPrecision = 1.0f;
1208 }
1209
1210 // Configure touch and tool area ranges.
1211 float diagonal = sqrt(float(width * width + height * height));
1212 float diagonalFuzz = sqrt(mXScale * mXScale + mYScale * mYScale);
1213
1214 mOrientedRanges.touchMajor.min = 0.0f;
1215 mOrientedRanges.touchMajor.max = diagonal;
1216 mOrientedRanges.touchMajor.flat = 0.0f;
1217 mOrientedRanges.touchMajor.fuzz = diagonalFuzz;
1218 mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
1219
1220 mOrientedRanges.toolMinor = mOrientedRanges.toolMajor = mOrientedRanges.touchMajor;
1221 }
1222
1223 if (orientationChanged || sizeChanged) {
1224 // Compute oriented surface dimensions, precision, and scales.
1225 float orientedXScale, orientedYScale;
1226 switch (mSurfaceOrientation) {
1227 case InputReaderPolicyInterface::ROTATION_90:
1228 case InputReaderPolicyInterface::ROTATION_270:
1229 mOrientedSurfaceWidth = mSurfaceHeight;
1230 mOrientedSurfaceHeight = mSurfaceWidth;
1231 mOrientedXPrecision = mYPrecision;
1232 mOrientedYPrecision = mXPrecision;
1233 orientedXScale = mYScale;
1234 orientedYScale = mXScale;
1235 break;
1236 default:
1237 mOrientedSurfaceWidth = mSurfaceWidth;
1238 mOrientedSurfaceHeight = mSurfaceHeight;
1239 mOrientedXPrecision = mXPrecision;
1240 mOrientedYPrecision = mYPrecision;
1241 orientedXScale = mXScale;
1242 orientedYScale = mYScale;
1243 break;
1244 }
1245
1246 // Configure position ranges.
1247 mOrientedRanges.x.min = 0;
1248 mOrientedRanges.x.max = mOrientedSurfaceWidth;
1249 mOrientedRanges.x.flat = 0;
1250 mOrientedRanges.x.fuzz = orientedXScale;
1251
1252 mOrientedRanges.y.min = 0;
1253 mOrientedRanges.y.max = mOrientedSurfaceHeight;
1254 mOrientedRanges.y.flat = 0;
1255 mOrientedRanges.y.fuzz = orientedYScale;
1256 }
1257
1258 return true;
1259}
1260
1261void TouchInputMapper::configureVirtualKeys() {
1262 assert(mAxes.x.valid && mAxes.y.valid);
1263
1264 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
1265 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1266
1267 { // acquire virtual key lock
1268 AutoMutex _l(mVirtualKeyLock);
1269
1270 mVirtualKeys.clear();
1271
1272 if (virtualKeyDefinitions.size() == 0) {
1273 return;
1274 }
1275
1276 mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
1277
1278 int32_t touchScreenLeft = mAxes.x.minValue;
1279 int32_t touchScreenTop = mAxes.y.minValue;
1280 int32_t touchScreenWidth = mAxes.x.getRange();
1281 int32_t touchScreenHeight = mAxes.y.getRange();
1282
1283 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
1284 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
1285 virtualKeyDefinitions[i];
1286
1287 mVirtualKeys.add();
1288 VirtualKey& virtualKey = mVirtualKeys.editTop();
1289
1290 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1291 int32_t keyCode;
1292 uint32_t flags;
1293 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1294 & keyCode, & flags)) {
1295 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1296 mVirtualKeys.pop(); // drop the key
1297 continue;
1298 }
1299
1300 virtualKey.keyCode = keyCode;
1301 virtualKey.flags = flags;
1302
1303 // convert the key definition's display coordinates into touch coordinates for a hit box
1304 int32_t halfWidth = virtualKeyDefinition.width / 2;
1305 int32_t halfHeight = virtualKeyDefinition.height / 2;
1306
1307 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1308 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
1309 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1310 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
1311 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1312 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
1313 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1314 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
1315
1316 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1317 virtualKey.scanCode, virtualKey.keyCode,
1318 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1319 }
1320 } // release virtual key lock
1321}
1322
1323void TouchInputMapper::reset() {
1324 // Synthesize touch up event if touch is currently down.
1325 // This will also take care of finishing virtual key processing if needed.
1326 if (mLastTouch.pointerCount != 0) {
1327 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1328 mCurrentTouch.clear();
1329 syncTouch(when, true);
1330 }
1331
1332 InputMapper::reset();
1333
1334 // Reinitialize.
1335 initialize();
1336}
1337
1338void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
1339 /* Refresh associated display information and update our size configuration if needed. */
1340
1341 if (! configureSurface()) {
1342 return;
1343 }
1344
1345 /* Apply policy */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001346
1347 uint32_t policyFlags = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001348 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1349
1350 if (! applyStandardPolicyActions(when, policyActions)) {
1351 mLastTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001352 return; // event dropped
1353 }
1354
1355 /* Preprocess pointer data */
1356
Jeff Brown6d0fec22010-07-23 21:28:06 -07001357 if (mParameters.useBadTouchFilter) {
1358 if (applyBadTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001359 havePointerIds = false;
1360 }
1361 }
1362
Jeff Brown6d0fec22010-07-23 21:28:06 -07001363 if (mParameters.useJumpyTouchFilter) {
1364 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001365 havePointerIds = false;
1366 }
1367 }
1368
1369 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001370 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001371 }
1372
Jeff Brown6d0fec22010-07-23 21:28:06 -07001373 TouchData temp;
1374 TouchData* savedTouch;
1375 if (mParameters.useAveragingTouchFilter) {
1376 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001377 savedTouch = & temp;
1378
Jeff Brown6d0fec22010-07-23 21:28:06 -07001379 applyAveragingTouchFilter();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001380 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001381 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001382 }
1383
Jeff Brown6d0fec22010-07-23 21:28:06 -07001384 /* Process touches and virtual keys */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001385
Jeff Brown6d0fec22010-07-23 21:28:06 -07001386 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
1387 if (touchResult == DISPATCH_TOUCH) {
1388 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001389 }
1390
Jeff Brown6d0fec22010-07-23 21:28:06 -07001391 /* Copy current touch to last touch in preparation for the next cycle. */
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001392
Jeff Brown6d0fec22010-07-23 21:28:06 -07001393 if (touchResult == DROP_STROKE) {
1394 mLastTouch.clear();
1395 } else {
1396 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001397 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001398}
1399
Jeff Brown6d0fec22010-07-23 21:28:06 -07001400TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
1401 nsecs_t when, uint32_t policyFlags) {
1402 int32_t keyEventAction, keyEventFlags;
1403 int32_t keyCode, scanCode, downTime;
1404 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07001405
Jeff Brown6d0fec22010-07-23 21:28:06 -07001406 { // acquire virtual key lock
1407 AutoMutex _l(mVirtualKeyLock);
1408
1409 if (mCurrentVirtualKey.down) {
1410 if (mCurrentTouch.pointerCount == 0) {
1411 // Pointer went up while virtual key was down.
1412 mCurrentVirtualKey.down = false;
1413#if DEBUG_VIRTUAL_KEYS
1414 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1415 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1416#endif
1417 keyEventAction = AKEY_EVENT_ACTION_UP;
1418 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1419 touchResult = SKIP_TOUCH;
1420 goto DispatchVirtualKey;
1421 }
1422
1423 if (mCurrentTouch.pointerCount == 1) {
1424 int32_t x = mCurrentTouch.pointers[0].x;
1425 int32_t y = mCurrentTouch.pointers[0].y;
1426 const VirtualKey* virtualKey = findVirtualKeyHitLvk(x, y);
1427 if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
1428 // Pointer is still within the space of the virtual key.
1429 return SKIP_TOUCH;
1430 }
1431 }
1432
1433 // Pointer left virtual key area or another pointer also went down.
1434 // Send key cancellation and drop the stroke so subsequent motions will be
1435 // considered fresh downs. This is useful when the user swipes away from the
1436 // virtual key area into the main display surface.
1437 mCurrentVirtualKey.down = false;
1438#if DEBUG_VIRTUAL_KEYS
1439 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1440 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1441#endif
1442 keyEventAction = AKEY_EVENT_ACTION_UP;
1443 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1444 | AKEY_EVENT_FLAG_CANCELED;
1445 touchResult = DROP_STROKE;
1446 goto DispatchVirtualKey;
1447 } else {
1448 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
1449 // Pointer just went down. Handle off-screen touches, if needed.
1450 int32_t x = mCurrentTouch.pointers[0].x;
1451 int32_t y = mCurrentTouch.pointers[0].y;
1452 if (! isPointInsideSurface(x, y)) {
1453 // If exactly one pointer went down, check for virtual key hit.
1454 // Otherwise we will drop the entire stroke.
1455 if (mCurrentTouch.pointerCount == 1) {
1456 const VirtualKey* virtualKey = findVirtualKeyHitLvk(x, y);
1457 if (virtualKey) {
1458 mCurrentVirtualKey.down = true;
1459 mCurrentVirtualKey.downTime = when;
1460 mCurrentVirtualKey.keyCode = virtualKey->keyCode;
1461 mCurrentVirtualKey.scanCode = virtualKey->scanCode;
1462#if DEBUG_VIRTUAL_KEYS
1463 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1464 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1465#endif
1466 keyEventAction = AKEY_EVENT_ACTION_DOWN;
1467 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
1468 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1469 touchResult = SKIP_TOUCH;
1470 goto DispatchVirtualKey;
1471 }
1472 }
1473 return DROP_STROKE;
1474 }
1475 }
1476 return DISPATCH_TOUCH;
1477 }
1478
1479 DispatchVirtualKey:
1480 // Collect remaining state needed to dispatch virtual key.
1481 keyCode = mCurrentVirtualKey.keyCode;
1482 scanCode = mCurrentVirtualKey.scanCode;
1483 downTime = mCurrentVirtualKey.downTime;
1484 } // release virtual key lock
1485
1486 // Dispatch virtual key.
1487 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001488
Jeff Brownc5ed5912010-07-14 18:48:53 -07001489 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001490 getPolicy()->virtualKeyDownFeedback();
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001491 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001492
Jeff Brown6d0fec22010-07-23 21:28:06 -07001493 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brownc5ed5912010-07-14 18:48:53 -07001494 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -07001495
Jeff Brown6d0fec22010-07-23 21:28:06 -07001496 if (applyStandardPolicyActions(when, policyActions)) {
1497 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -07001498 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1499 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001500 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001501}
1502
Jeff Brown6d0fec22010-07-23 21:28:06 -07001503void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
1504 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1505 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001506 if (currentPointerCount == 0 && lastPointerCount == 0) {
1507 return; // nothing to do!
1508 }
1509
Jeff Brown6d0fec22010-07-23 21:28:06 -07001510 BitSet32 currentIdBits = mCurrentTouch.idBits;
1511 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001512
1513 if (currentIdBits == lastIdBits) {
1514 // No pointer id changes so this is a move event.
1515 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001516 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001517 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -07001518 currentIdBits, -1, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001519 } else {
1520 // There may be pointers going up and pointers going down at the same time when pointer
1521 // ids are reported by the device driver.
1522 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1523 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1524 BitSet32 activeIdBits(lastIdBits.value);
1525
1526 while (! upIdBits.isEmpty()) {
1527 uint32_t upId = upIdBits.firstMarkedBit();
1528 upIdBits.clearBit(upId);
1529 BitSet32 oldActiveIdBits = activeIdBits;
1530 activeIdBits.clearBit(upId);
1531
1532 int32_t motionEventAction;
1533 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001534 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001535 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07001536 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001537 }
1538
Jeff Brown6d0fec22010-07-23 21:28:06 -07001539 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -07001540 oldActiveIdBits, upId, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001541 }
1542
1543 while (! downIdBits.isEmpty()) {
1544 uint32_t downId = downIdBits.firstMarkedBit();
1545 downIdBits.clearBit(downId);
1546 BitSet32 oldActiveIdBits = activeIdBits;
1547 activeIdBits.markBit(downId);
1548
1549 int32_t motionEventAction;
1550 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001551 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001552 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001553 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07001554 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001555 }
1556
Jeff Brown6d0fec22010-07-23 21:28:06 -07001557 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -07001558 activeIdBits, downId, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001559 }
1560 }
1561}
1562
Jeff Brown6d0fec22010-07-23 21:28:06 -07001563void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
1564 TouchData* touch, BitSet32 idBits, uint32_t changedId,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001565 int32_t motionEventAction) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001566 uint32_t pointerCount = 0;
1567 int32_t pointerIds[MAX_POINTERS];
1568 PointerCoords pointerCoords[MAX_POINTERS];
1569
1570 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1571 // display coordinates (PointerCoords) and adjust for display orientation.
1572 while (! idBits.isEmpty()) {
1573 uint32_t id = idBits.firstMarkedBit();
1574 idBits.clearBit(id);
1575 uint32_t index = touch->idToIndex[id];
1576
Jeff Brown6d0fec22010-07-23 21:28:06 -07001577 float x = float(touch->pointers[index].x - mXOrigin) * mXScale;
1578 float y = float(touch->pointers[index].y - mYOrigin) * mYScale;
1579 float pressure = float(touch->pointers[index].pressure - mPressureOrigin) * mPressureScale;
1580 float size = float(touch->pointers[index].size - mSizeOrigin) * mSizeScale;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001581
Jeff Brown6d0fec22010-07-23 21:28:06 -07001582 float orientation = float(touch->pointers[index].orientation) * mOrientationScale;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001583
Jeff Brown6d0fec22010-07-23 21:28:06 -07001584 float touchMajor, touchMinor, toolMajor, toolMinor;
1585 if (abs(orientation) <= M_PI_4) {
1586 // Nominally vertical orientation: scale major axis by Y, and scale minor axis by X.
1587 touchMajor = float(touch->pointers[index].touchMajor) * mYScale;
1588 touchMinor = float(touch->pointers[index].touchMinor) * mXScale;
1589 toolMajor = float(touch->pointers[index].toolMajor) * mYScale;
1590 toolMinor = float(touch->pointers[index].toolMinor) * mXScale;
1591 } else {
1592 // Nominally horizontal orientation: scale major axis by X, and scale minor axis by Y.
1593 touchMajor = float(touch->pointers[index].touchMajor) * mXScale;
1594 touchMinor = float(touch->pointers[index].touchMinor) * mYScale;
1595 toolMajor = float(touch->pointers[index].toolMajor) * mXScale;
1596 toolMinor = float(touch->pointers[index].toolMinor) * mYScale;
1597 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001598
Jeff Brown6d0fec22010-07-23 21:28:06 -07001599 switch (mSurfaceOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001600 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001601 float xTemp = x;
1602 x = y;
Jeff Brownaab985b2010-07-29 13:05:52 -07001603 y = mSurfaceWidth - xTemp;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001604 orientation -= M_PI_2;
1605 if (orientation < - M_PI_2) {
1606 orientation += M_PI;
1607 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001608 break;
1609 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001610 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Brownaab985b2010-07-29 13:05:52 -07001611 x = mSurfaceWidth - x;
1612 y = mSurfaceHeight - y;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001613 orientation = - orientation;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001614 break;
1615 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001616 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001617 float xTemp = x;
Jeff Brownaab985b2010-07-29 13:05:52 -07001618 x = mSurfaceHeight - y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001619 y = xTemp;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001620 orientation += M_PI_2;
1621 if (orientation > M_PI_2) {
1622 orientation -= M_PI;
1623 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001624 break;
1625 }
1626 }
1627
1628 pointerIds[pointerCount] = int32_t(id);
1629
1630 pointerCoords[pointerCount].x = x;
1631 pointerCoords[pointerCount].y = y;
1632 pointerCoords[pointerCount].pressure = pressure;
1633 pointerCoords[pointerCount].size = size;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001634 pointerCoords[pointerCount].touchMajor = touchMajor;
1635 pointerCoords[pointerCount].touchMinor = touchMinor;
1636 pointerCoords[pointerCount].toolMajor = toolMajor;
1637 pointerCoords[pointerCount].toolMinor = toolMinor;
1638 pointerCoords[pointerCount].orientation = orientation;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001639
Jeff Brown00ba8842010-07-16 15:01:56 -07001640 if (id == changedId) {
1641 motionEventAction |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
1642 }
1643
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001644 pointerCount += 1;
1645 }
1646
1647 // Check edge flags by looking only at the first pointer since the flags are
1648 // global to the event.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001649 int32_t motionEventEdgeFlags = 0;
Jeff Brownc5ed5912010-07-14 18:48:53 -07001650 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001651 if (pointerCoords[0].x <= 0) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001652 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001653 } else if (pointerCoords[0].x >= mOrientedSurfaceWidth) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001654 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001655 }
1656 if (pointerCoords[0].y <= 0) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001657 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001658 } else if (pointerCoords[0].y >= mOrientedSurfaceHeight) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001659 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001660 }
1661 }
1662
Jeff Brown6d0fec22010-07-23 21:28:06 -07001663 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
1664 motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001665 pointerCount, pointerIds, pointerCoords,
Jeff Brown6d0fec22010-07-23 21:28:06 -07001666 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001667}
1668
Jeff Brown6d0fec22010-07-23 21:28:06 -07001669bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
1670 if (mAxes.x.valid && mAxes.y.valid) {
1671 return x >= mAxes.x.minValue && x <= mAxes.x.maxValue
1672 && y >= mAxes.y.minValue && y <= mAxes.y.maxValue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001673 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001674 return true;
1675}
1676
1677const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLvk(int32_t x, int32_t y) {
1678 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
1679 const VirtualKey& virtualKey = mVirtualKeys[i];
1680
1681#if DEBUG_VIRTUAL_KEYS
1682 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
1683 "left=%d, top=%d, right=%d, bottom=%d",
1684 x, y,
1685 virtualKey.keyCode, virtualKey.scanCode,
1686 virtualKey.hitLeft, virtualKey.hitTop,
1687 virtualKey.hitRight, virtualKey.hitBottom);
1688#endif
1689
1690 if (virtualKey.isHit(x, y)) {
1691 return & virtualKey;
1692 }
1693 }
1694
1695 return NULL;
1696}
1697
1698void TouchInputMapper::calculatePointerIds() {
1699 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1700 uint32_t lastPointerCount = mLastTouch.pointerCount;
1701
1702 if (currentPointerCount == 0) {
1703 // No pointers to assign.
1704 mCurrentTouch.idBits.clear();
1705 } else if (lastPointerCount == 0) {
1706 // All pointers are new.
1707 mCurrentTouch.idBits.clear();
1708 for (uint32_t i = 0; i < currentPointerCount; i++) {
1709 mCurrentTouch.pointers[i].id = i;
1710 mCurrentTouch.idToIndex[i] = i;
1711 mCurrentTouch.idBits.markBit(i);
1712 }
1713 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
1714 // Only one pointer and no change in count so it must have the same id as before.
1715 uint32_t id = mLastTouch.pointers[0].id;
1716 mCurrentTouch.pointers[0].id = id;
1717 mCurrentTouch.idToIndex[id] = 0;
1718 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
1719 } else {
1720 // General case.
1721 // We build a heap of squared euclidean distances between current and last pointers
1722 // associated with the current and last pointer indices. Then, we find the best
1723 // match (by distance) for each current pointer.
1724 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
1725
1726 uint32_t heapSize = 0;
1727 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
1728 currentPointerIndex++) {
1729 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
1730 lastPointerIndex++) {
1731 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
1732 - mLastTouch.pointers[lastPointerIndex].x;
1733 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
1734 - mLastTouch.pointers[lastPointerIndex].y;
1735
1736 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
1737
1738 // Insert new element into the heap (sift up).
1739 heap[heapSize].currentPointerIndex = currentPointerIndex;
1740 heap[heapSize].lastPointerIndex = lastPointerIndex;
1741 heap[heapSize].distance = distance;
1742 heapSize += 1;
1743 }
1744 }
1745
1746 // Heapify
1747 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
1748 startIndex -= 1;
1749 for (uint32_t parentIndex = startIndex; ;) {
1750 uint32_t childIndex = parentIndex * 2 + 1;
1751 if (childIndex >= heapSize) {
1752 break;
1753 }
1754
1755 if (childIndex + 1 < heapSize
1756 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1757 childIndex += 1;
1758 }
1759
1760 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1761 break;
1762 }
1763
1764 swap(heap[parentIndex], heap[childIndex]);
1765 parentIndex = childIndex;
1766 }
1767 }
1768
1769#if DEBUG_POINTER_ASSIGNMENT
1770 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
1771 for (size_t i = 0; i < heapSize; i++) {
1772 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1773 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1774 heap[i].distance);
1775 }
1776#endif
1777
1778 // Pull matches out by increasing order of distance.
1779 // To avoid reassigning pointers that have already been matched, the loop keeps track
1780 // of which last and current pointers have been matched using the matchedXXXBits variables.
1781 // It also tracks the used pointer id bits.
1782 BitSet32 matchedLastBits(0);
1783 BitSet32 matchedCurrentBits(0);
1784 BitSet32 usedIdBits(0);
1785 bool first = true;
1786 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
1787 for (;;) {
1788 if (first) {
1789 // The first time through the loop, we just consume the root element of
1790 // the heap (the one with smallest distance).
1791 first = false;
1792 } else {
1793 // Previous iterations consumed the root element of the heap.
1794 // Pop root element off of the heap (sift down).
1795 heapSize -= 1;
1796 assert(heapSize > 0);
1797
1798 // Sift down.
1799 heap[0] = heap[heapSize];
1800 for (uint32_t parentIndex = 0; ;) {
1801 uint32_t childIndex = parentIndex * 2 + 1;
1802 if (childIndex >= heapSize) {
1803 break;
1804 }
1805
1806 if (childIndex + 1 < heapSize
1807 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1808 childIndex += 1;
1809 }
1810
1811 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1812 break;
1813 }
1814
1815 swap(heap[parentIndex], heap[childIndex]);
1816 parentIndex = childIndex;
1817 }
1818
1819#if DEBUG_POINTER_ASSIGNMENT
1820 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
1821 for (size_t i = 0; i < heapSize; i++) {
1822 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1823 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1824 heap[i].distance);
1825 }
1826#endif
1827 }
1828
1829 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
1830 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
1831
1832 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
1833 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
1834
1835 matchedCurrentBits.markBit(currentPointerIndex);
1836 matchedLastBits.markBit(lastPointerIndex);
1837
1838 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
1839 mCurrentTouch.pointers[currentPointerIndex].id = id;
1840 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1841 usedIdBits.markBit(id);
1842
1843#if DEBUG_POINTER_ASSIGNMENT
1844 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
1845 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
1846#endif
1847 break;
1848 }
1849 }
1850
1851 // Assign fresh ids to new pointers.
1852 if (currentPointerCount > lastPointerCount) {
1853 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
1854 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
1855 uint32_t id = usedIdBits.firstUnmarkedBit();
1856
1857 mCurrentTouch.pointers[currentPointerIndex].id = id;
1858 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1859 usedIdBits.markBit(id);
1860
1861#if DEBUG_POINTER_ASSIGNMENT
1862 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
1863 currentPointerIndex, id);
1864#endif
1865
1866 if (--i == 0) break; // done
1867 matchedCurrentBits.markBit(currentPointerIndex);
1868 }
1869 }
1870
1871 // Fix id bits.
1872 mCurrentTouch.idBits = usedIdBits;
1873 }
1874}
1875
1876/* Special hack for devices that have bad screen data: if one of the
1877 * points has moved more than a screen height from the last position,
1878 * then drop it. */
1879bool TouchInputMapper::applyBadTouchFilter() {
1880 // This hack requires valid axis parameters.
1881 if (! mAxes.y.valid) {
1882 return false;
1883 }
1884
1885 uint32_t pointerCount = mCurrentTouch.pointerCount;
1886
1887 // Nothing to do if there are no points.
1888 if (pointerCount == 0) {
1889 return false;
1890 }
1891
1892 // Don't do anything if a finger is going down or up. We run
1893 // here before assigning pointer IDs, so there isn't a good
1894 // way to do per-finger matching.
1895 if (pointerCount != mLastTouch.pointerCount) {
1896 return false;
1897 }
1898
1899 // We consider a single movement across more than a 7/16 of
1900 // the long size of the screen to be bad. This was a magic value
1901 // determined by looking at the maximum distance it is feasible
1902 // to actually move in one sample.
1903 int32_t maxDeltaY = mAxes.y.getRange() * 7 / 16;
1904
1905 // XXX The original code in InputDevice.java included commented out
1906 // code for testing the X axis. Note that when we drop a point
1907 // we don't actually restore the old X either. Strange.
1908 // The old code also tries to track when bad points were previously
1909 // detected but it turns out that due to the placement of a "break"
1910 // at the end of the loop, we never set mDroppedBadPoint to true
1911 // so it is effectively dead code.
1912 // Need to figure out if the old code is busted or just overcomplicated
1913 // but working as intended.
1914
1915 // Look through all new points and see if any are farther than
1916 // acceptable from all previous points.
1917 for (uint32_t i = pointerCount; i-- > 0; ) {
1918 int32_t y = mCurrentTouch.pointers[i].y;
1919 int32_t closestY = INT_MAX;
1920 int32_t closestDeltaY = 0;
1921
1922#if DEBUG_HACKS
1923 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
1924#endif
1925
1926 for (uint32_t j = pointerCount; j-- > 0; ) {
1927 int32_t lastY = mLastTouch.pointers[j].y;
1928 int32_t deltaY = abs(y - lastY);
1929
1930#if DEBUG_HACKS
1931 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
1932 j, lastY, deltaY);
1933#endif
1934
1935 if (deltaY < maxDeltaY) {
1936 goto SkipSufficientlyClosePoint;
1937 }
1938 if (deltaY < closestDeltaY) {
1939 closestDeltaY = deltaY;
1940 closestY = lastY;
1941 }
1942 }
1943
1944 // Must not have found a close enough match.
1945#if DEBUG_HACKS
1946 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
1947 i, y, closestY, closestDeltaY, maxDeltaY);
1948#endif
1949
1950 mCurrentTouch.pointers[i].y = closestY;
1951 return true; // XXX original code only corrects one point
1952
1953 SkipSufficientlyClosePoint: ;
1954 }
1955
1956 // No change.
1957 return false;
1958}
1959
1960/* Special hack for devices that have bad screen data: drop points where
1961 * the coordinate value for one axis has jumped to the other pointer's location.
1962 */
1963bool TouchInputMapper::applyJumpyTouchFilter() {
1964 // This hack requires valid axis parameters.
1965 if (! mAxes.y.valid) {
1966 return false;
1967 }
1968
1969 uint32_t pointerCount = mCurrentTouch.pointerCount;
1970 if (mLastTouch.pointerCount != pointerCount) {
1971#if DEBUG_HACKS
1972 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
1973 mLastTouch.pointerCount, pointerCount);
1974 for (uint32_t i = 0; i < pointerCount; i++) {
1975 LOGD(" Pointer %d (%d, %d)", i,
1976 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
1977 }
1978#endif
1979
1980 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
1981 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
1982 // Just drop the first few events going from 1 to 2 pointers.
1983 // They're bad often enough that they're not worth considering.
1984 mCurrentTouch.pointerCount = 1;
1985 mJumpyTouchFilter.jumpyPointsDropped += 1;
1986
1987#if DEBUG_HACKS
1988 LOGD("JumpyTouchFilter: Pointer 2 dropped");
1989#endif
1990 return true;
1991 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
1992 // The event when we go from 2 -> 1 tends to be messed up too
1993 mCurrentTouch.pointerCount = 2;
1994 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
1995 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
1996 mJumpyTouchFilter.jumpyPointsDropped += 1;
1997
1998#if DEBUG_HACKS
1999 for (int32_t i = 0; i < 2; i++) {
2000 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2001 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2002 }
2003#endif
2004 return true;
2005 }
2006 }
2007 // Reset jumpy points dropped on other transitions or if limit exceeded.
2008 mJumpyTouchFilter.jumpyPointsDropped = 0;
2009
2010#if DEBUG_HACKS
2011 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2012#endif
2013 return false;
2014 }
2015
2016 // We have the same number of pointers as last time.
2017 // A 'jumpy' point is one where the coordinate value for one axis
2018 // has jumped to the other pointer's location. No need to do anything
2019 // else if we only have one pointer.
2020 if (pointerCount < 2) {
2021 return false;
2022 }
2023
2024 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
2025 int jumpyEpsilon = mAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
2026
2027 // We only replace the single worst jumpy point as characterized by pointer distance
2028 // in a single axis.
2029 int32_t badPointerIndex = -1;
2030 int32_t badPointerReplacementIndex = -1;
2031 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2032
2033 for (uint32_t i = pointerCount; i-- > 0; ) {
2034 int32_t x = mCurrentTouch.pointers[i].x;
2035 int32_t y = mCurrentTouch.pointers[i].y;
2036
2037#if DEBUG_HACKS
2038 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2039#endif
2040
2041 // Check if a touch point is too close to another's coordinates
2042 bool dropX = false, dropY = false;
2043 for (uint32_t j = 0; j < pointerCount; j++) {
2044 if (i == j) {
2045 continue;
2046 }
2047
2048 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2049 dropX = true;
2050 break;
2051 }
2052
2053 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2054 dropY = true;
2055 break;
2056 }
2057 }
2058 if (! dropX && ! dropY) {
2059 continue; // not jumpy
2060 }
2061
2062 // Find a replacement candidate by comparing with older points on the
2063 // complementary (non-jumpy) axis.
2064 int32_t distance = INT_MIN; // distance to be corrected
2065 int32_t replacementIndex = -1;
2066
2067 if (dropX) {
2068 // X looks too close. Find an older replacement point with a close Y.
2069 int32_t smallestDeltaY = INT_MAX;
2070 for (uint32_t j = 0; j < pointerCount; j++) {
2071 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2072 if (deltaY < smallestDeltaY) {
2073 smallestDeltaY = deltaY;
2074 replacementIndex = j;
2075 }
2076 }
2077 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2078 } else {
2079 // Y looks too close. Find an older replacement point with a close X.
2080 int32_t smallestDeltaX = INT_MAX;
2081 for (uint32_t j = 0; j < pointerCount; j++) {
2082 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2083 if (deltaX < smallestDeltaX) {
2084 smallestDeltaX = deltaX;
2085 replacementIndex = j;
2086 }
2087 }
2088 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2089 }
2090
2091 // If replacing this pointer would correct a worse error than the previous ones
2092 // considered, then use this replacement instead.
2093 if (distance > badPointerDistance) {
2094 badPointerIndex = i;
2095 badPointerReplacementIndex = replacementIndex;
2096 badPointerDistance = distance;
2097 }
2098 }
2099
2100 // Correct the jumpy pointer if one was found.
2101 if (badPointerIndex >= 0) {
2102#if DEBUG_HACKS
2103 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2104 badPointerIndex,
2105 mLastTouch.pointers[badPointerReplacementIndex].x,
2106 mLastTouch.pointers[badPointerReplacementIndex].y);
2107#endif
2108
2109 mCurrentTouch.pointers[badPointerIndex].x =
2110 mLastTouch.pointers[badPointerReplacementIndex].x;
2111 mCurrentTouch.pointers[badPointerIndex].y =
2112 mLastTouch.pointers[badPointerReplacementIndex].y;
2113 mJumpyTouchFilter.jumpyPointsDropped += 1;
2114 return true;
2115 }
2116 }
2117
2118 mJumpyTouchFilter.jumpyPointsDropped = 0;
2119 return false;
2120}
2121
2122/* Special hack for devices that have bad screen data: aggregate and
2123 * compute averages of the coordinate data, to reduce the amount of
2124 * jitter seen by applications. */
2125void TouchInputMapper::applyAveragingTouchFilter() {
2126 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2127 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2128 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2129 int32_t y = mCurrentTouch.pointers[currentIndex].y;
2130 int32_t pressure = mCurrentTouch.pointers[currentIndex].pressure;
2131
2132 if (mLastTouch.idBits.hasBit(id)) {
2133 // Pointer was down before and is still down now.
2134 // Compute average over history trace.
2135 uint32_t start = mAveragingTouchFilter.historyStart[id];
2136 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2137
2138 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2139 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2140 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2141
2142#if DEBUG_HACKS
2143 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2144 id, distance);
2145#endif
2146
2147 if (distance < AVERAGING_DISTANCE_LIMIT) {
2148 // Increment end index in preparation for recording new historical data.
2149 end += 1;
2150 if (end > AVERAGING_HISTORY_SIZE) {
2151 end = 0;
2152 }
2153
2154 // If the end index has looped back to the start index then we have filled
2155 // the historical trace up to the desired size so we drop the historical
2156 // data at the start of the trace.
2157 if (end == start) {
2158 start += 1;
2159 if (start > AVERAGING_HISTORY_SIZE) {
2160 start = 0;
2161 }
2162 }
2163
2164 // Add the raw data to the historical trace.
2165 mAveragingTouchFilter.historyStart[id] = start;
2166 mAveragingTouchFilter.historyEnd[id] = end;
2167 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2168 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2169 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2170
2171 // Average over all historical positions in the trace by total pressure.
2172 int32_t averagedX = 0;
2173 int32_t averagedY = 0;
2174 int32_t totalPressure = 0;
2175 for (;;) {
2176 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2177 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2178 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2179 .pointers[id].pressure;
2180
2181 averagedX += historicalX * historicalPressure;
2182 averagedY += historicalY * historicalPressure;
2183 totalPressure += historicalPressure;
2184
2185 if (start == end) {
2186 break;
2187 }
2188
2189 start += 1;
2190 if (start > AVERAGING_HISTORY_SIZE) {
2191 start = 0;
2192 }
2193 }
2194
2195 averagedX /= totalPressure;
2196 averagedY /= totalPressure;
2197
2198#if DEBUG_HACKS
2199 LOGD("AveragingTouchFilter: Pointer id %d - "
2200 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2201 averagedX, averagedY);
2202#endif
2203
2204 mCurrentTouch.pointers[currentIndex].x = averagedX;
2205 mCurrentTouch.pointers[currentIndex].y = averagedY;
2206 } else {
2207#if DEBUG_HACKS
2208 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2209#endif
2210 }
2211 } else {
2212#if DEBUG_HACKS
2213 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2214#endif
2215 }
2216
2217 // Reset pointer history.
2218 mAveragingTouchFilter.historyStart[id] = 0;
2219 mAveragingTouchFilter.historyEnd[id] = 0;
2220 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2221 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2222 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
2223 }
2224}
2225
2226int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
2227 { // acquire virtual key lock
2228 AutoMutex _l(mVirtualKeyLock);
2229
2230 if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
2231 return AKEY_STATE_VIRTUAL;
2232 }
2233
2234 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
2235 const VirtualKey& virtualKey = mVirtualKeys[i];
2236 if (virtualKey.keyCode == keyCode) {
2237 return AKEY_STATE_UP;
2238 }
2239 }
2240 } // release virtual key lock
2241
2242 return AKEY_STATE_UNKNOWN;
2243}
2244
2245int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
2246 { // acquire virtual key lock
2247 AutoMutex _l(mVirtualKeyLock);
2248
2249 if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
2250 return AKEY_STATE_VIRTUAL;
2251 }
2252
2253 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
2254 const VirtualKey& virtualKey = mVirtualKeys[i];
2255 if (virtualKey.scanCode == scanCode) {
2256 return AKEY_STATE_UP;
2257 }
2258 }
2259 } // release virtual key lock
2260
2261 return AKEY_STATE_UNKNOWN;
2262}
2263
2264bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2265 const int32_t* keyCodes, uint8_t* outFlags) {
2266 { // acquire virtual key lock
2267 AutoMutex _l(mVirtualKeyLock);
2268
2269 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
2270 const VirtualKey& virtualKey = mVirtualKeys[i];
2271
2272 for (size_t i = 0; i < numCodes; i++) {
2273 if (virtualKey.keyCode == keyCodes[i]) {
2274 outFlags[i] = 1;
2275 }
2276 }
2277 }
2278 } // release virtual key lock
2279
2280 return true;
2281}
2282
2283
2284// --- SingleTouchInputMapper ---
2285
2286SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2287 TouchInputMapper(device, associatedDisplayId) {
2288 initialize();
2289}
2290
2291SingleTouchInputMapper::~SingleTouchInputMapper() {
2292}
2293
2294void SingleTouchInputMapper::initialize() {
2295 mAccumulator.clear();
2296
2297 mDown = false;
2298 mX = 0;
2299 mY = 0;
2300 mPressure = 0;
2301 mSize = 0;
2302}
2303
2304void SingleTouchInputMapper::reset() {
2305 TouchInputMapper::reset();
2306
2307 // Reinitialize.
2308 initialize();
2309 }
2310
2311void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
2312 switch (rawEvent->type) {
2313 case EV_KEY:
2314 switch (rawEvent->scanCode) {
2315 case BTN_TOUCH:
2316 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
2317 mAccumulator.btnTouch = rawEvent->value != 0;
2318
2319 sync(rawEvent->when);
2320 mAccumulator.clear();
2321 break;
2322 }
2323 break;
2324
2325 case EV_ABS:
2326 switch (rawEvent->scanCode) {
2327 case ABS_X:
2328 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
2329 mAccumulator.absX = rawEvent->value;
2330 break;
2331 case ABS_Y:
2332 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
2333 mAccumulator.absY = rawEvent->value;
2334 break;
2335 case ABS_PRESSURE:
2336 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
2337 mAccumulator.absPressure = rawEvent->value;
2338 break;
2339 case ABS_TOOL_WIDTH:
2340 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
2341 mAccumulator.absToolWidth = rawEvent->value;
2342 break;
2343 }
2344 break;
2345
2346 case EV_SYN:
2347 switch (rawEvent->scanCode) {
2348 case SYN_REPORT:
2349 if (mAccumulator.isDirty()) {
2350 sync(rawEvent->when);
2351 mAccumulator.clear();
2352 }
2353 break;
2354 }
2355 break;
2356 }
2357}
2358
2359void SingleTouchInputMapper::sync(nsecs_t when) {
2360 /* Update device state */
2361
2362 uint32_t fields = mAccumulator.fields;
2363
2364 if (fields & Accumulator::FIELD_BTN_TOUCH) {
2365 mDown = mAccumulator.btnTouch;
2366 }
2367
2368 if (fields & Accumulator::FIELD_ABS_X) {
2369 mX = mAccumulator.absX;
2370 }
2371
2372 if (fields & Accumulator::FIELD_ABS_Y) {
2373 mY = mAccumulator.absY;
2374 }
2375
2376 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
2377 mPressure = mAccumulator.absPressure;
2378 }
2379
2380 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
2381 mSize = mAccumulator.absToolWidth;
2382 }
2383
2384 mCurrentTouch.clear();
2385
2386 if (mDown) {
2387 mCurrentTouch.pointerCount = 1;
2388 mCurrentTouch.pointers[0].id = 0;
2389 mCurrentTouch.pointers[0].x = mX;
2390 mCurrentTouch.pointers[0].y = mY;
2391 mCurrentTouch.pointers[0].pressure = mPressure;
2392 mCurrentTouch.pointers[0].size = mSize;
2393 mCurrentTouch.pointers[0].touchMajor = mPressure;
2394 mCurrentTouch.pointers[0].touchMinor = mPressure;
2395 mCurrentTouch.pointers[0].toolMajor = mSize;
2396 mCurrentTouch.pointers[0].toolMinor = mSize;
2397 mCurrentTouch.pointers[0].orientation = 0;
2398 mCurrentTouch.idToIndex[0] = 0;
2399 mCurrentTouch.idBits.markBit(0);
2400 }
2401
2402 syncTouch(when, true);
2403}
2404
2405void SingleTouchInputMapper::configureAxes() {
2406 TouchInputMapper::configureAxes();
2407
2408 // The axes are aliased to take into account the manner in which they are presented
2409 // as part of the TouchData during the sync.
2410 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mAxes.x);
2411 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mAxes.y);
2412 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure);
2413 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size);
2414
2415 mAxes.touchMajor = mAxes.pressure;
2416 mAxes.touchMinor = mAxes.pressure;
2417 mAxes.toolMajor = mAxes.size;
2418 mAxes.toolMinor = mAxes.size;
2419}
2420
2421
2422// --- MultiTouchInputMapper ---
2423
2424MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2425 TouchInputMapper(device, associatedDisplayId) {
2426 initialize();
2427}
2428
2429MultiTouchInputMapper::~MultiTouchInputMapper() {
2430}
2431
2432void MultiTouchInputMapper::initialize() {
2433 mAccumulator.clear();
2434}
2435
2436void MultiTouchInputMapper::reset() {
2437 TouchInputMapper::reset();
2438
2439 // Reinitialize.
2440 initialize();
2441}
2442
2443void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
2444 switch (rawEvent->type) {
2445 case EV_ABS: {
2446 uint32_t pointerIndex = mAccumulator.pointerCount;
2447 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
2448
2449 switch (rawEvent->scanCode) {
2450 case ABS_MT_POSITION_X:
2451 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
2452 pointer->absMTPositionX = rawEvent->value;
2453 break;
2454 case ABS_MT_POSITION_Y:
2455 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
2456 pointer->absMTPositionY = rawEvent->value;
2457 break;
2458 case ABS_MT_TOUCH_MAJOR:
2459 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
2460 pointer->absMTTouchMajor = rawEvent->value;
2461 break;
2462 case ABS_MT_TOUCH_MINOR:
2463 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
2464 pointer->absMTTouchMinor = rawEvent->value;
2465 break;
2466 case ABS_MT_WIDTH_MAJOR:
2467 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
2468 pointer->absMTWidthMajor = rawEvent->value;
2469 break;
2470 case ABS_MT_WIDTH_MINOR:
2471 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
2472 pointer->absMTWidthMinor = rawEvent->value;
2473 break;
2474 case ABS_MT_ORIENTATION:
2475 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
2476 pointer->absMTOrientation = rawEvent->value;
2477 break;
2478 case ABS_MT_TRACKING_ID:
2479 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
2480 pointer->absMTTrackingId = rawEvent->value;
2481 break;
2482 }
2483 break;
2484 }
2485
2486 case EV_SYN:
2487 switch (rawEvent->scanCode) {
2488 case SYN_MT_REPORT: {
2489 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
2490 uint32_t pointerIndex = mAccumulator.pointerCount;
2491
2492 if (mAccumulator.pointers[pointerIndex].fields) {
2493 if (pointerIndex == MAX_POINTERS) {
2494 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
2495 MAX_POINTERS);
2496 } else {
2497 pointerIndex += 1;
2498 mAccumulator.pointerCount = pointerIndex;
2499 }
2500 }
2501
2502 mAccumulator.pointers[pointerIndex].clear();
2503 break;
2504 }
2505
2506 case SYN_REPORT:
2507 if (mAccumulator.isDirty()) {
2508 sync(rawEvent->when);
2509 mAccumulator.clear();
2510 }
2511 break;
2512 }
2513 break;
2514 }
2515}
2516
2517void MultiTouchInputMapper::sync(nsecs_t when) {
2518 static const uint32_t REQUIRED_FIELDS =
2519 Accumulator::FIELD_ABS_MT_POSITION_X
2520 | Accumulator::FIELD_ABS_MT_POSITION_Y
2521 | Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
2522 | Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002523
2524 /* Update device state */
2525
Jeff Brown6d0fec22010-07-23 21:28:06 -07002526 uint32_t inCount = mAccumulator.pointerCount;
2527 uint32_t outCount = 0;
2528 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002529
Jeff Brown6d0fec22010-07-23 21:28:06 -07002530 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002531
Jeff Brown6d0fec22010-07-23 21:28:06 -07002532 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
2533 uint32_t fields = mAccumulator.pointers[inIndex].fields;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002534
Jeff Brown6d0fec22010-07-23 21:28:06 -07002535 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
2536#if DEBUG_POINTERS
2537 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
2538 inIndex, fields);
2539 continue;
2540#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002541 }
2542
Jeff Brown6d0fec22010-07-23 21:28:06 -07002543 if (mAccumulator.pointers[inIndex].absMTTouchMajor <= 0) {
2544 // Pointer is not down. Drop it.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002545 continue;
2546 }
2547
Jeff Brown6d0fec22010-07-23 21:28:06 -07002548 mCurrentTouch.pointers[outCount].x = mAccumulator.pointers[inIndex].absMTPositionX;
2549 mCurrentTouch.pointers[outCount].y = mAccumulator.pointers[inIndex].absMTPositionY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002550
Jeff Brown6d0fec22010-07-23 21:28:06 -07002551 mCurrentTouch.pointers[outCount].touchMajor =
2552 mAccumulator.pointers[inIndex].absMTTouchMajor;
2553 mCurrentTouch.pointers[outCount].touchMinor =
2554 (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
2555 ? mAccumulator.pointers[inIndex].absMTTouchMinor
2556 : mAccumulator.pointers[inIndex].absMTTouchMajor;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002557
Jeff Brown6d0fec22010-07-23 21:28:06 -07002558 mCurrentTouch.pointers[outCount].toolMajor =
2559 mAccumulator.pointers[inIndex].absMTWidthMajor;
2560 mCurrentTouch.pointers[outCount].toolMinor =
2561 (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
2562 ? mAccumulator.pointers[inIndex].absMTWidthMinor
2563 : mAccumulator.pointers[inIndex].absMTWidthMajor;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002564
Jeff Brown6d0fec22010-07-23 21:28:06 -07002565 mCurrentTouch.pointers[outCount].orientation =
2566 (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
2567 ? mAccumulator.pointers[inIndex].absMTOrientation : 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002568
Jeff Brown6d0fec22010-07-23 21:28:06 -07002569 // Derive an approximation of pressure and size.
2570 // FIXME assignment of pressure may be incorrect, probably better to let
2571 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
2572 // isn't quite right either. Should be using touch for that.
2573 mCurrentTouch.pointers[outCount].pressure = mAccumulator.pointers[inIndex].absMTTouchMajor;
2574 mCurrentTouch.pointers[outCount].size = mAccumulator.pointers[inIndex].absMTWidthMajor;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002575
Jeff Brown6d0fec22010-07-23 21:28:06 -07002576 if (havePointerIds) {
2577 if (fields & Accumulator::
2578 FIELD_ABS_MT_TRACKING_ID) {
2579 uint32_t id = uint32_t(mAccumulator.pointers[inIndex].absMTTrackingId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002580
Jeff Brown6d0fec22010-07-23 21:28:06 -07002581 if (id > MAX_POINTER_ID) {
2582#if DEBUG_POINTERS
2583 LOGD("Pointers: Ignoring driver provided pointer id %d because "
2584 "it is larger than max supported id %d for optimizations",
2585 id, MAX_POINTER_ID);
2586#endif
2587 havePointerIds = false;
2588 }
2589 else {
2590 mCurrentTouch.pointers[outCount].id = id;
2591 mCurrentTouch.idToIndex[id] = outCount;
2592 mCurrentTouch.idBits.markBit(id);
2593 }
2594 } else {
2595 havePointerIds = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002596 }
2597 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002598
Jeff Brown6d0fec22010-07-23 21:28:06 -07002599 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002600 }
2601
Jeff Brown6d0fec22010-07-23 21:28:06 -07002602 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002603
Jeff Brown6d0fec22010-07-23 21:28:06 -07002604 syncTouch(when, havePointerIds);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002605}
2606
Jeff Brown6d0fec22010-07-23 21:28:06 -07002607void MultiTouchInputMapper::configureAxes() {
2608 TouchInputMapper::configureAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002609
Jeff Brown6d0fec22010-07-23 21:28:06 -07002610 // The axes are aliased to take into account the manner in which they are presented
2611 // as part of the TouchData during the sync.
2612 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mAxes.x);
2613 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mAxes.y);
2614 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mAxes.touchMajor);
2615 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mAxes.touchMinor);
2616 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor);
2617 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor);
2618 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002619
Jeff Brown6d0fec22010-07-23 21:28:06 -07002620 if (! mAxes.touchMinor.valid) {
2621 mAxes.touchMinor = mAxes.touchMajor;
Jeff Brown9c3cda02010-06-15 01:31:58 -07002622 }
2623
Jeff Brown6d0fec22010-07-23 21:28:06 -07002624 if (! mAxes.toolMinor.valid) {
2625 mAxes.toolMinor = mAxes.toolMajor;
2626 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07002627
Jeff Brown6d0fec22010-07-23 21:28:06 -07002628 mAxes.pressure = mAxes.touchMajor;
2629 mAxes.size = mAxes.toolMajor;
Jeff Brown9c3cda02010-06-15 01:31:58 -07002630}
2631
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002632
2633} // namespace android