blob: 5f5a4ac4e6446d17f04ad1a121ee81d6fab40be4 [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070021
Jeff Brown5c225b12010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Brown46b9ac02010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070056int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
57 int32_t mask;
58 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -070059 case AKEYCODE_ALT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070060 mask = AMETA_ALT_LEFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070061 break;
Jeff Brownfd035822010-06-30 16:10:35 -070062 case AKEYCODE_ALT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070063 mask = AMETA_ALT_RIGHT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070064 break;
Jeff Brownfd035822010-06-30 16:10:35 -070065 case AKEYCODE_SHIFT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070066 mask = AMETA_SHIFT_LEFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070067 break;
Jeff Brownfd035822010-06-30 16:10:35 -070068 case AKEYCODE_SHIFT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070069 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070070 break;
Jeff Brownfd035822010-06-30 16:10:35 -070071 case AKEYCODE_SYM:
Jeff Brownc5ed5912010-07-14 18:48:53 -070072 mask = AMETA_SYM_ON;
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brownfd035822010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700118
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700158 break;
159
Jeff Brown6d0fec22010-07-23 21:28:06 -0700160 default:
161 consumeEvent(rawEvent);
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700374 }
375 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700716 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700717}
718
719KeyboardInputMapper::~KeyboardInputMapper() {
720}
721
Jeff Brown6328cdc2010-07-29 18:18:33 -0700722void KeyboardInputMapper::initializeLocked() {
723 mLocked.metaState = AMETA_NONE;
724 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700725}
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() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700738 for (;;) {
739 int32_t keyCode, scanCode;
740 { // acquire lock
741 AutoMutex _l(mLock);
742
743 // Synthesize key up event on reset if keys are currently down.
744 if (mLocked.keyDowns.isEmpty()) {
745 initializeLocked();
746 break; // done
747 }
748
749 const KeyDown& keyDown = mLocked.keyDowns.top();
750 keyCode = keyDown.keyCode;
751 scanCode = keyDown.scanCode;
752 } // release lock
753
Jeff Brown6d0fec22010-07-23 21:28:06 -0700754 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700755 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700756 }
757
758 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700759 getContext()->updateGlobalMetaState();
760}
761
762void KeyboardInputMapper::process(const RawEvent* rawEvent) {
763 switch (rawEvent->type) {
764 case EV_KEY: {
765 int32_t scanCode = rawEvent->scanCode;
766 if (isKeyboardOrGamepadKey(scanCode)) {
767 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
768 rawEvent->flags);
769 }
770 break;
771 }
772 }
773}
774
775bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
776 return scanCode < BTN_MOUSE
777 || scanCode >= KEY_OK
778 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
779}
780
Jeff Brown6328cdc2010-07-29 18:18:33 -0700781void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
782 int32_t scanCode, uint32_t policyFlags) {
783 int32_t newMetaState;
784 nsecs_t downTime;
785 bool metaStateChanged = false;
786
787 { // acquire lock
788 AutoMutex _l(mLock);
789
790 if (down) {
791 // Rotate key codes according to orientation if needed.
792 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
793 if (mAssociatedDisplayId >= 0) {
794 int32_t orientation;
795 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
796 return;
797 }
798
799 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700800 }
801
Jeff Brown6328cdc2010-07-29 18:18:33 -0700802 // Add key down.
803 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
804 if (keyDownIndex >= 0) {
805 // key repeat, be sure to use same keycode as before in case of rotation
806 keyCode = mLocked.keyDowns.top().keyCode;
807 } else {
808 // key down
809 mLocked.keyDowns.push();
810 KeyDown& keyDown = mLocked.keyDowns.editTop();
811 keyDown.keyCode = keyCode;
812 keyDown.scanCode = scanCode;
813 }
814
815 mLocked.downTime = when;
816 } else {
817 // Remove key down.
818 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
819 if (keyDownIndex >= 0) {
820 // key up, be sure to use same keycode as before in case of rotation
821 keyCode = mLocked.keyDowns.top().keyCode;
822 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
823 } else {
824 // key was not actually down
825 LOGI("Dropping key up from device %s because the key was not down. "
826 "keyCode=%d, scanCode=%d",
827 getDeviceName().string(), keyCode, scanCode);
828 return;
829 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700830 }
831
Jeff Brown6328cdc2010-07-29 18:18:33 -0700832 int32_t oldMetaState = mLocked.metaState;
833 newMetaState = updateMetaState(keyCode, down, oldMetaState);
834 if (oldMetaState != newMetaState) {
835 mLocked.metaState = newMetaState;
836 metaStateChanged = true;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700837 }
Jeff Brownfd035822010-06-30 16:10:35 -0700838
Jeff Brown6328cdc2010-07-29 18:18:33 -0700839 downTime = mLocked.downTime;
840 } // release lock
841
842 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700843 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700844 }
845
Jeff Brown6328cdc2010-07-29 18:18:33 -0700846 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
847}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700848
Jeff Brown6328cdc2010-07-29 18:18:33 -0700849void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
850 int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700851 int32_t policyActions = getPolicy()->interceptKey(when,
852 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700853
Jeff Brown6d0fec22010-07-23 21:28:06 -0700854 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700855 return; // event dropped
856 }
857
Jeff Brown6328cdc2010-07-29 18:18:33 -0700858 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700859 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700860 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700861 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700862 }
863
Jeff Brown6d0fec22010-07-23 21:28:06 -0700864 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown6328cdc2010-07-29 18:18:33 -0700865 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700866}
867
Jeff Brown6328cdc2010-07-29 18:18:33 -0700868ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
869 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700870 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700871 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700872 return i;
873 }
874 }
875 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700876}
877
Jeff Brown6d0fec22010-07-23 21:28:06 -0700878int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
879 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
880}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700881
Jeff Brown6d0fec22010-07-23 21:28:06 -0700882int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
883 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
884}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700885
Jeff Brown6d0fec22010-07-23 21:28:06 -0700886bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
887 const int32_t* keyCodes, uint8_t* outFlags) {
888 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
889}
890
891int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700892 { // acquire lock
893 AutoMutex _l(mLock);
894 return mLocked.metaState;
895 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700896}
897
898
899// --- TrackballInputMapper ---
900
901TrackballInputMapper::TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId) :
902 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
903 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
904 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
905 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
906 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
907
Jeff Brown6328cdc2010-07-29 18:18:33 -0700908 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700909}
910
911TrackballInputMapper::~TrackballInputMapper() {
912}
913
914uint32_t TrackballInputMapper::getSources() {
915 return AINPUT_SOURCE_TRACKBALL;
916}
917
918void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
919 InputMapper::populateDeviceInfo(info);
920
921 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
922 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
923}
924
Jeff Brown6328cdc2010-07-29 18:18:33 -0700925void TrackballInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700926 mAccumulator.clear();
927
Jeff Brown6328cdc2010-07-29 18:18:33 -0700928 mLocked.down = false;
929 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700930}
931
932void TrackballInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700933 for (;;) {
934 { // acquire lock
935 AutoMutex _l(mLock);
936
937 if (! mLocked.down) {
938 initializeLocked();
939 break; // done
940 }
941 } // release lock
942
943 // Synthesize trackball button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700944 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700945 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700946 mAccumulator.btnMouse = false;
947 sync(when);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700948 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700949 }
950
Jeff Brown6d0fec22010-07-23 21:28:06 -0700951 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700952}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700953
Jeff Brown6d0fec22010-07-23 21:28:06 -0700954void TrackballInputMapper::process(const RawEvent* rawEvent) {
955 switch (rawEvent->type) {
956 case EV_KEY:
957 switch (rawEvent->scanCode) {
958 case BTN_MOUSE:
959 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
960 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700961
Jeff Brown6d0fec22010-07-23 21:28:06 -0700962 sync(rawEvent->when);
963 mAccumulator.clear();
964 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700965 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700966 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700967
Jeff Brown6d0fec22010-07-23 21:28:06 -0700968 case EV_REL:
969 switch (rawEvent->scanCode) {
970 case REL_X:
971 mAccumulator.fields |= Accumulator::FIELD_REL_X;
972 mAccumulator.relX = rawEvent->value;
973 break;
974 case REL_Y:
975 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
976 mAccumulator.relY = rawEvent->value;
977 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700978 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700979 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700980
Jeff Brown6d0fec22010-07-23 21:28:06 -0700981 case EV_SYN:
982 switch (rawEvent->scanCode) {
983 case SYN_REPORT:
984 if (mAccumulator.isDirty()) {
985 sync(rawEvent->when);
986 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700987 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700988 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700989 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700990 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700991 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700992}
993
Jeff Brown6d0fec22010-07-23 21:28:06 -0700994void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700995 int motionEventAction;
996 PointerCoords pointerCoords;
997 nsecs_t downTime;
998 { // acquire lock
999 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001000
Jeff Brown6328cdc2010-07-29 18:18:33 -07001001 uint32_t fields = mAccumulator.fields;
1002 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1003
1004 if (downChanged) {
1005 if (mAccumulator.btnMouse) {
1006 mLocked.down = true;
1007 mLocked.downTime = when;
1008 } else {
1009 mLocked.down = false;
1010 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001011 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001012
Jeff Brown6328cdc2010-07-29 18:18:33 -07001013 downTime = mLocked.downTime;
1014 float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1015 float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001016
Jeff Brown6328cdc2010-07-29 18:18:33 -07001017 if (downChanged) {
1018 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001019 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001020 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001021 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001022
Jeff Brown6328cdc2010-07-29 18:18:33 -07001023 pointerCoords.x = x;
1024 pointerCoords.y = y;
1025 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1026 pointerCoords.size = 0;
1027 pointerCoords.touchMajor = 0;
1028 pointerCoords.touchMinor = 0;
1029 pointerCoords.toolMajor = 0;
1030 pointerCoords.toolMinor = 0;
1031 pointerCoords.orientation = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001032
Jeff Brown6328cdc2010-07-29 18:18:33 -07001033 if (mAssociatedDisplayId >= 0 && (x != 0.0f || y != 0.0f)) {
1034 // Rotate motion based on display orientation if needed.
1035 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1036 int32_t orientation;
1037 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
1038 return;
1039 }
1040
1041 float temp;
1042 switch (orientation) {
1043 case InputReaderPolicyInterface::ROTATION_90:
1044 temp = pointerCoords.x;
1045 pointerCoords.x = pointerCoords.y;
1046 pointerCoords.y = - temp;
1047 break;
1048
1049 case InputReaderPolicyInterface::ROTATION_180:
1050 pointerCoords.x = - pointerCoords.x;
1051 pointerCoords.y = - pointerCoords.y;
1052 break;
1053
1054 case InputReaderPolicyInterface::ROTATION_270:
1055 temp = pointerCoords.x;
1056 pointerCoords.x = - pointerCoords.y;
1057 pointerCoords.y = temp;
1058 break;
1059 }
1060 }
1061 } // release lock
1062
1063 applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
1064}
1065
1066void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1067 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001068 uint32_t policyFlags = 0;
1069 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1070
1071 if (! applyStandardPolicyActions(when, policyActions)) {
1072 return; // event dropped
1073 }
1074
Jeff Brown6d0fec22010-07-23 21:28:06 -07001075 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001076 int32_t pointerId = 0;
1077
Jeff Brown6d0fec22010-07-23 21:28:06 -07001078 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
1079 motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001080 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001081}
1082
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001083int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1084 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1085 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1086 } else {
1087 return AKEY_STATE_UNKNOWN;
1088 }
1089}
1090
Jeff Brown6d0fec22010-07-23 21:28:06 -07001091
1092// --- TouchInputMapper ---
1093
1094TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brown6328cdc2010-07-29 18:18:33 -07001095 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1096 mLocked.surfaceOrientation = -1;
1097 mLocked.surfaceWidth = -1;
1098 mLocked.surfaceHeight = -1;
1099
1100 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001101}
1102
1103TouchInputMapper::~TouchInputMapper() {
1104}
1105
1106uint32_t TouchInputMapper::getSources() {
1107 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1108}
1109
1110void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1111 InputMapper::populateDeviceInfo(info);
1112
Jeff Brown6328cdc2010-07-29 18:18:33 -07001113 { // acquire lock
1114 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001115
Jeff Brown6328cdc2010-07-29 18:18:33 -07001116 // Ensure surface information is up to date so that orientation changes are
1117 // noticed immediately.
1118 configureSurfaceLocked();
1119
1120 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1121 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
1122 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, mLocked.orientedRanges.pressure);
1123 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE, mLocked.orientedRanges.size);
1124 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR, mLocked.orientedRanges.touchMajor);
1125 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR, mLocked.orientedRanges.touchMinor);
1126 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR, mLocked.orientedRanges.toolMajor);
1127 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR, mLocked.orientedRanges.toolMinor);
1128 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION, mLocked.orientedRanges.orientation);
1129 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001130}
1131
Jeff Brown6328cdc2010-07-29 18:18:33 -07001132void TouchInputMapper::initializeLocked() {
1133 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001134 mLastTouch.clear();
1135 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001136
1137 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1138 mAveragingTouchFilter.historyStart[i] = 0;
1139 mAveragingTouchFilter.historyEnd[i] = 0;
1140 }
1141
1142 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001143
1144 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001145}
1146
1147void TouchInputMapper::configure() {
1148 InputMapper::configure();
1149
1150 // Configure basic parameters.
1151 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1152 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1153 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1154
1155 // Configure absolute axis information.
1156 configureAxes();
1157
Jeff Brown6328cdc2010-07-29 18:18:33 -07001158 { // acquire lock
1159 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001160
Jeff Brown6328cdc2010-07-29 18:18:33 -07001161 // Configure pressure factors.
1162 if (mAxes.pressure.valid) {
1163 mLocked.pressureOrigin = mAxes.pressure.minValue;
1164 mLocked.pressureScale = 1.0f / mAxes.pressure.getRange();
1165 } else {
1166 mLocked.pressureOrigin = 0;
1167 mLocked.pressureScale = 1.0f;
1168 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001169
Jeff Brown6328cdc2010-07-29 18:18:33 -07001170 mLocked.orientedRanges.pressure.min = 0.0f;
1171 mLocked.orientedRanges.pressure.max = 1.0f;
1172 mLocked.orientedRanges.pressure.flat = 0.0f;
1173 mLocked.orientedRanges.pressure.fuzz = mLocked.pressureScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001174
Jeff Brown6328cdc2010-07-29 18:18:33 -07001175 // Configure size factors.
1176 if (mAxes.size.valid) {
1177 mLocked.sizeOrigin = mAxes.size.minValue;
1178 mLocked.sizeScale = 1.0f / mAxes.size.getRange();
1179 } else {
1180 mLocked.sizeOrigin = 0;
1181 mLocked.sizeScale = 1.0f;
1182 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001183
Jeff Brown6328cdc2010-07-29 18:18:33 -07001184 mLocked.orientedRanges.size.min = 0.0f;
1185 mLocked.orientedRanges.size.max = 1.0f;
1186 mLocked.orientedRanges.size.flat = 0.0f;
1187 mLocked.orientedRanges.size.fuzz = mLocked.sizeScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001188
Jeff Brown6328cdc2010-07-29 18:18:33 -07001189 // Configure orientation factors.
1190 if (mAxes.orientation.valid && mAxes.orientation.maxValue > 0) {
1191 mLocked.orientationScale = float(M_PI_2) / mAxes.orientation.maxValue;
1192 } else {
1193 mLocked.orientationScale = 0.0f;
1194 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001195
Jeff Brown6328cdc2010-07-29 18:18:33 -07001196 mLocked.orientedRanges.orientation.min = - M_PI_2;
1197 mLocked.orientedRanges.orientation.max = M_PI_2;
1198 mLocked.orientedRanges.orientation.flat = 0;
1199 mLocked.orientedRanges.orientation.fuzz = mLocked.orientationScale;
1200
1201 // Configure surface dimensions and orientation.
1202 configureSurfaceLocked();
1203 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001204}
1205
1206void TouchInputMapper::configureAxes() {
1207 mAxes.x.valid = false;
1208 mAxes.y.valid = false;
1209 mAxes.pressure.valid = false;
1210 mAxes.size.valid = false;
1211 mAxes.touchMajor.valid = false;
1212 mAxes.touchMinor.valid = false;
1213 mAxes.toolMajor.valid = false;
1214 mAxes.toolMinor.valid = false;
1215 mAxes.orientation.valid = false;
1216}
1217
Jeff Brown6328cdc2010-07-29 18:18:33 -07001218bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001219 // Update orientation and dimensions if needed.
1220 int32_t orientation;
1221 int32_t width, height;
1222 if (mAssociatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001223 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001224 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1225 return false;
1226 }
1227 } else {
1228 orientation = InputReaderPolicyInterface::ROTATION_0;
1229 width = mAxes.x.getRange();
1230 height = mAxes.y.getRange();
1231 }
1232
Jeff Brown6328cdc2010-07-29 18:18:33 -07001233 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001234 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001235 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001236 }
1237
Jeff Brown6328cdc2010-07-29 18:18:33 -07001238 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001239 if (sizeChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001240 mLocked.surfaceWidth = width;
1241 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001242
1243 // Compute size-dependent translation and scaling factors and place virtual keys.
1244 if (mAxes.x.valid && mAxes.y.valid) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001245 mLocked.xOrigin = mAxes.x.minValue;
1246 mLocked.yOrigin = mAxes.y.minValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001247
1248 LOGI("Device configured: id=0x%x, name=%s (display size was changed)",
1249 getDeviceId(), getDeviceName().string());
1250
Jeff Brown6328cdc2010-07-29 18:18:33 -07001251 mLocked.xScale = float(width) / mAxes.x.getRange();
1252 mLocked.yScale = float(height) / mAxes.y.getRange();
1253 mLocked.xPrecision = 1.0f / mLocked.xScale;
1254 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001255
Jeff Brown6328cdc2010-07-29 18:18:33 -07001256 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001257 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001258 mLocked.xOrigin = 0;
1259 mLocked.yOrigin = 0;
1260 mLocked.xScale = 1.0f;
1261 mLocked.yScale = 1.0f;
1262 mLocked.xPrecision = 1.0f;
1263 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001264 }
1265
1266 // Configure touch and tool area ranges.
1267 float diagonal = sqrt(float(width * width + height * height));
Jeff Brown6328cdc2010-07-29 18:18:33 -07001268 float diagonalFuzz = sqrt(mLocked.xScale * mLocked.xScale
1269 + mLocked.yScale * mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001270
Jeff Brown6328cdc2010-07-29 18:18:33 -07001271 InputDeviceInfo::MotionRange area;
1272 area.min = 0.0f;
1273 area.max = diagonal;
1274 area.flat = 0.0f;
1275 area.fuzz = diagonalFuzz;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001276
Jeff Brown6328cdc2010-07-29 18:18:33 -07001277 mLocked.orientedRanges.touchMajor = area;
1278 mLocked.orientedRanges.touchMinor = area;
1279
1280 mLocked.orientedRanges.toolMajor = area;
1281 mLocked.orientedRanges.toolMinor = area;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001282 }
1283
1284 if (orientationChanged || sizeChanged) {
1285 // Compute oriented surface dimensions, precision, and scales.
1286 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001287 switch (mLocked.surfaceOrientation) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001288 case InputReaderPolicyInterface::ROTATION_90:
1289 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001290 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1291 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1292 mLocked.orientedXPrecision = mLocked.yPrecision;
1293 mLocked.orientedYPrecision = mLocked.xPrecision;
1294 orientedXScale = mLocked.yScale;
1295 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001296 break;
1297 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001298 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1299 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1300 mLocked.orientedXPrecision = mLocked.xPrecision;
1301 mLocked.orientedYPrecision = mLocked.yPrecision;
1302 orientedXScale = mLocked.xScale;
1303 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001304 break;
1305 }
1306
1307 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001308 mLocked.orientedRanges.x.min = 0;
1309 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1310 mLocked.orientedRanges.x.flat = 0;
1311 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001312
Jeff Brown6328cdc2010-07-29 18:18:33 -07001313 mLocked.orientedRanges.y.min = 0;
1314 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1315 mLocked.orientedRanges.y.flat = 0;
1316 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001317 }
1318
1319 return true;
1320}
1321
Jeff Brown6328cdc2010-07-29 18:18:33 -07001322void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001323 assert(mAxes.x.valid && mAxes.y.valid);
1324
Jeff Brown6328cdc2010-07-29 18:18:33 -07001325 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001326 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
1327 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1328
Jeff Brown6328cdc2010-07-29 18:18:33 -07001329 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001330
Jeff Brown6328cdc2010-07-29 18:18:33 -07001331 if (virtualKeyDefinitions.size() == 0) {
1332 return;
1333 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001334
Jeff Brown6328cdc2010-07-29 18:18:33 -07001335 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1336
1337 int32_t touchScreenLeft = mAxes.x.minValue;
1338 int32_t touchScreenTop = mAxes.y.minValue;
1339 int32_t touchScreenWidth = mAxes.x.getRange();
1340 int32_t touchScreenHeight = mAxes.y.getRange();
1341
1342 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
1343 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
1344 virtualKeyDefinitions[i];
1345
1346 mLocked.virtualKeys.add();
1347 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1348
1349 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1350 int32_t keyCode;
1351 uint32_t flags;
1352 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1353 & keyCode, & flags)) {
1354 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1355 mLocked.virtualKeys.pop(); // drop the key
1356 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001357 }
1358
Jeff Brown6328cdc2010-07-29 18:18:33 -07001359 virtualKey.keyCode = keyCode;
1360 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001361
Jeff Brown6328cdc2010-07-29 18:18:33 -07001362 // convert the key definition's display coordinates into touch coordinates for a hit box
1363 int32_t halfWidth = virtualKeyDefinition.width / 2;
1364 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001365
Jeff Brown6328cdc2010-07-29 18:18:33 -07001366 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1367 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1368 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1369 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1370 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1371 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1372 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1373 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001374
Jeff Brown6328cdc2010-07-29 18:18:33 -07001375 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1376 virtualKey.scanCode, virtualKey.keyCode,
1377 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1378 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001379}
1380
1381void TouchInputMapper::reset() {
1382 // Synthesize touch up event if touch is currently down.
1383 // This will also take care of finishing virtual key processing if needed.
1384 if (mLastTouch.pointerCount != 0) {
1385 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1386 mCurrentTouch.clear();
1387 syncTouch(when, true);
1388 }
1389
Jeff Brown6328cdc2010-07-29 18:18:33 -07001390 { // acquire lock
1391 AutoMutex _l(mLock);
1392 initializeLocked();
1393 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001394
Jeff Brown6328cdc2010-07-29 18:18:33 -07001395 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001396}
1397
1398void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001399 // Apply generic policy actions.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001400
1401 uint32_t policyFlags = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001402 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1403
1404 if (! applyStandardPolicyActions(when, policyActions)) {
1405 mLastTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001406 return; // event dropped
1407 }
1408
Jeff Brown6328cdc2010-07-29 18:18:33 -07001409 // Preprocess pointer data.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001410
Jeff Brown6d0fec22010-07-23 21:28:06 -07001411 if (mParameters.useBadTouchFilter) {
1412 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001413 havePointerIds = false;
1414 }
1415 }
1416
Jeff Brown6d0fec22010-07-23 21:28:06 -07001417 if (mParameters.useJumpyTouchFilter) {
1418 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001419 havePointerIds = false;
1420 }
1421 }
1422
1423 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001424 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001425 }
1426
Jeff Brown6d0fec22010-07-23 21:28:06 -07001427 TouchData temp;
1428 TouchData* savedTouch;
1429 if (mParameters.useAveragingTouchFilter) {
1430 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001431 savedTouch = & temp;
1432
Jeff Brown6d0fec22010-07-23 21:28:06 -07001433 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001434 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001435 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001436 }
1437
Jeff Brown6328cdc2010-07-29 18:18:33 -07001438 // Process touches and virtual keys.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001439
Jeff Brown6d0fec22010-07-23 21:28:06 -07001440 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
1441 if (touchResult == DISPATCH_TOUCH) {
1442 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001443 }
1444
Jeff Brown6328cdc2010-07-29 18:18:33 -07001445 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001446
Jeff Brown6d0fec22010-07-23 21:28:06 -07001447 if (touchResult == DROP_STROKE) {
1448 mLastTouch.clear();
1449 } else {
1450 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001451 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001452}
1453
Jeff Brown6d0fec22010-07-23 21:28:06 -07001454TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
1455 nsecs_t when, uint32_t policyFlags) {
1456 int32_t keyEventAction, keyEventFlags;
1457 int32_t keyCode, scanCode, downTime;
1458 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07001459
Jeff Brown6328cdc2010-07-29 18:18:33 -07001460 { // acquire lock
1461 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001462
Jeff Brown6328cdc2010-07-29 18:18:33 -07001463 // Update surface size and orientation, including virtual key positions.
1464 if (! configureSurfaceLocked()) {
1465 return DROP_STROKE;
1466 }
1467
1468 // Check for virtual key press.
1469 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001470 if (mCurrentTouch.pointerCount == 0) {
1471 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001472 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001473#if DEBUG_VIRTUAL_KEYS
1474 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1475 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1476#endif
1477 keyEventAction = AKEY_EVENT_ACTION_UP;
1478 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1479 touchResult = SKIP_TOUCH;
1480 goto DispatchVirtualKey;
1481 }
1482
1483 if (mCurrentTouch.pointerCount == 1) {
1484 int32_t x = mCurrentTouch.pointers[0].x;
1485 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001486 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
1487 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001488 // Pointer is still within the space of the virtual key.
1489 return SKIP_TOUCH;
1490 }
1491 }
1492
1493 // Pointer left virtual key area or another pointer also went down.
1494 // Send key cancellation and drop the stroke so subsequent motions will be
1495 // considered fresh downs. This is useful when the user swipes away from the
1496 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001497 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001498#if DEBUG_VIRTUAL_KEYS
1499 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1500 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1501#endif
1502 keyEventAction = AKEY_EVENT_ACTION_UP;
1503 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1504 | AKEY_EVENT_FLAG_CANCELED;
1505 touchResult = DROP_STROKE;
1506 goto DispatchVirtualKey;
1507 } else {
1508 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
1509 // Pointer just went down. Handle off-screen touches, if needed.
1510 int32_t x = mCurrentTouch.pointers[0].x;
1511 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001512 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001513 // If exactly one pointer went down, check for virtual key hit.
1514 // Otherwise we will drop the entire stroke.
1515 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001516 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001517 if (virtualKey) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001518 mLocked.currentVirtualKey.down = true;
1519 mLocked.currentVirtualKey.downTime = when;
1520 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
1521 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001522#if DEBUG_VIRTUAL_KEYS
1523 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1524 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1525#endif
1526 keyEventAction = AKEY_EVENT_ACTION_DOWN;
1527 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
1528 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1529 touchResult = SKIP_TOUCH;
1530 goto DispatchVirtualKey;
1531 }
1532 }
1533 return DROP_STROKE;
1534 }
1535 }
1536 return DISPATCH_TOUCH;
1537 }
1538
1539 DispatchVirtualKey:
1540 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001541 keyCode = mLocked.currentVirtualKey.keyCode;
1542 scanCode = mLocked.currentVirtualKey.scanCode;
1543 downTime = mLocked.currentVirtualKey.downTime;
1544 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001545
1546 // Dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001547 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
1548 keyCode, scanCode, downTime);
1549 return touchResult;
1550}
1551
1552void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
1553 int32_t keyEventAction, int32_t keyEventFlags,
1554 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001555 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001556
Jeff Brownc5ed5912010-07-14 18:48:53 -07001557 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001558 getPolicy()->virtualKeyDownFeedback();
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001559 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001560
Jeff Brown6d0fec22010-07-23 21:28:06 -07001561 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brownc5ed5912010-07-14 18:48:53 -07001562 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -07001563
Jeff Brown6d0fec22010-07-23 21:28:06 -07001564 if (applyStandardPolicyActions(when, policyActions)) {
1565 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -07001566 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1567 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001568}
1569
Jeff Brown6d0fec22010-07-23 21:28:06 -07001570void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
1571 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1572 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001573 if (currentPointerCount == 0 && lastPointerCount == 0) {
1574 return; // nothing to do!
1575 }
1576
Jeff Brown6d0fec22010-07-23 21:28:06 -07001577 BitSet32 currentIdBits = mCurrentTouch.idBits;
1578 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001579
1580 if (currentIdBits == lastIdBits) {
1581 // No pointer id changes so this is a move event.
1582 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07001583 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001584 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -07001585 currentIdBits, -1, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001586 } else {
1587 // There may be pointers going up and pointers going down at the same time when pointer
1588 // ids are reported by the device driver.
1589 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1590 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1591 BitSet32 activeIdBits(lastIdBits.value);
1592
1593 while (! upIdBits.isEmpty()) {
1594 uint32_t upId = upIdBits.firstMarkedBit();
1595 upIdBits.clearBit(upId);
1596 BitSet32 oldActiveIdBits = activeIdBits;
1597 activeIdBits.clearBit(upId);
1598
1599 int32_t motionEventAction;
1600 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001601 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001602 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07001603 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001604 }
1605
Jeff Brown6d0fec22010-07-23 21:28:06 -07001606 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -07001607 oldActiveIdBits, upId, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001608 }
1609
1610 while (! downIdBits.isEmpty()) {
1611 uint32_t downId = downIdBits.firstMarkedBit();
1612 downIdBits.clearBit(downId);
1613 BitSet32 oldActiveIdBits = activeIdBits;
1614 activeIdBits.markBit(downId);
1615
1616 int32_t motionEventAction;
1617 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001618 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001619 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001620 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07001621 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001622 }
1623
Jeff Brown6d0fec22010-07-23 21:28:06 -07001624 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -07001625 activeIdBits, downId, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001626 }
1627 }
1628}
1629
Jeff Brown6d0fec22010-07-23 21:28:06 -07001630void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
1631 TouchData* touch, BitSet32 idBits, uint32_t changedId,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001632 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001633 uint32_t pointerCount = 0;
1634 int32_t pointerIds[MAX_POINTERS];
1635 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac02010-04-22 18:58:52 -07001636 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001637 float xPrecision, yPrecision;
1638
1639 { // acquire lock
1640 AutoMutex _l(mLock);
1641
1642 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1643 // display coordinates (PointerCoords) and adjust for display orientation.
1644 while (! idBits.isEmpty()) {
1645 uint32_t id = idBits.firstMarkedBit();
1646 idBits.clearBit(id);
1647 uint32_t index = touch->idToIndex[id];
1648
1649 float x = float(touch->pointers[index].x - mLocked.xOrigin) * mLocked.xScale;
1650 float y = float(touch->pointers[index].y - mLocked.yOrigin) * mLocked.yScale;
1651 float pressure = float(touch->pointers[index].pressure - mLocked.pressureOrigin)
1652 * mLocked.pressureScale;
1653 float size = float(touch->pointers[index].size - mLocked.sizeOrigin)
1654 * mLocked.sizeScale;
1655
1656 float orientation = float(touch->pointers[index].orientation)
1657 * mLocked.orientationScale;
1658
1659 float touchMajor, touchMinor, toolMajor, toolMinor;
1660 if (abs(orientation) <= M_PI_4) {
1661 // Nominally vertical orientation: scale major axis by Y, and scale minor axis by X.
1662 touchMajor = float(touch->pointers[index].touchMajor) * mLocked.yScale;
1663 touchMinor = float(touch->pointers[index].touchMinor) * mLocked.xScale;
1664 toolMajor = float(touch->pointers[index].toolMajor) * mLocked.yScale;
1665 toolMinor = float(touch->pointers[index].toolMinor) * mLocked.xScale;
1666 } else {
1667 // Nominally horizontal orientation: scale major axis by X, and scale minor axis by Y.
1668 touchMajor = float(touch->pointers[index].touchMajor) * mLocked.xScale;
1669 touchMinor = float(touch->pointers[index].touchMinor) * mLocked.yScale;
1670 toolMajor = float(touch->pointers[index].toolMajor) * mLocked.xScale;
1671 toolMinor = float(touch->pointers[index].toolMinor) * mLocked.yScale;
1672 }
1673
1674 switch (mLocked.surfaceOrientation) {
1675 case InputReaderPolicyInterface::ROTATION_90: {
1676 float xTemp = x;
1677 x = y;
1678 y = mLocked.surfaceWidth - xTemp;
1679 orientation -= M_PI_2;
1680 if (orientation < - M_PI_2) {
1681 orientation += M_PI;
1682 }
1683 break;
1684 }
1685 case InputReaderPolicyInterface::ROTATION_180: {
1686 x = mLocked.surfaceWidth - x;
1687 y = mLocked.surfaceHeight - y;
1688 orientation = - orientation;
1689 break;
1690 }
1691 case InputReaderPolicyInterface::ROTATION_270: {
1692 float xTemp = x;
1693 x = mLocked.surfaceHeight - y;
1694 y = xTemp;
1695 orientation += M_PI_2;
1696 if (orientation > M_PI_2) {
1697 orientation -= M_PI;
1698 }
1699 break;
1700 }
1701 }
1702
1703 pointerIds[pointerCount] = int32_t(id);
1704
1705 pointerCoords[pointerCount].x = x;
1706 pointerCoords[pointerCount].y = y;
1707 pointerCoords[pointerCount].pressure = pressure;
1708 pointerCoords[pointerCount].size = size;
1709 pointerCoords[pointerCount].touchMajor = touchMajor;
1710 pointerCoords[pointerCount].touchMinor = touchMinor;
1711 pointerCoords[pointerCount].toolMajor = toolMajor;
1712 pointerCoords[pointerCount].toolMinor = toolMinor;
1713 pointerCoords[pointerCount].orientation = orientation;
1714
1715 if (id == changedId) {
1716 motionEventAction |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
1717 }
1718
1719 pointerCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001720 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001721
1722 // Check edge flags by looking only at the first pointer since the flags are
1723 // global to the event.
1724 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
1725 if (pointerCoords[0].x <= 0) {
1726 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
1727 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
1728 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
1729 }
1730 if (pointerCoords[0].y <= 0) {
1731 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
1732 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
1733 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
1734 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001735 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001736
1737 xPrecision = mLocked.orientedXPrecision;
1738 yPrecision = mLocked.orientedYPrecision;
1739 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07001740
Jeff Brown6d0fec22010-07-23 21:28:06 -07001741 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
1742 motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001743 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001744 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001745}
1746
Jeff Brown6328cdc2010-07-29 18:18:33 -07001747bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001748 if (mAxes.x.valid && mAxes.y.valid) {
1749 return x >= mAxes.x.minValue && x <= mAxes.x.maxValue
1750 && y >= mAxes.y.minValue && y <= mAxes.y.maxValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001751 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001752 return true;
1753}
1754
Jeff Brown6328cdc2010-07-29 18:18:33 -07001755const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
1756 int32_t x, int32_t y) {
1757 size_t numVirtualKeys = mLocked.virtualKeys.size();
1758 for (size_t i = 0; i < numVirtualKeys; i++) {
1759 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07001760
1761#if DEBUG_VIRTUAL_KEYS
1762 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
1763 "left=%d, top=%d, right=%d, bottom=%d",
1764 x, y,
1765 virtualKey.keyCode, virtualKey.scanCode,
1766 virtualKey.hitLeft, virtualKey.hitTop,
1767 virtualKey.hitRight, virtualKey.hitBottom);
1768#endif
1769
1770 if (virtualKey.isHit(x, y)) {
1771 return & virtualKey;
1772 }
1773 }
1774
1775 return NULL;
1776}
1777
1778void TouchInputMapper::calculatePointerIds() {
1779 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1780 uint32_t lastPointerCount = mLastTouch.pointerCount;
1781
1782 if (currentPointerCount == 0) {
1783 // No pointers to assign.
1784 mCurrentTouch.idBits.clear();
1785 } else if (lastPointerCount == 0) {
1786 // All pointers are new.
1787 mCurrentTouch.idBits.clear();
1788 for (uint32_t i = 0; i < currentPointerCount; i++) {
1789 mCurrentTouch.pointers[i].id = i;
1790 mCurrentTouch.idToIndex[i] = i;
1791 mCurrentTouch.idBits.markBit(i);
1792 }
1793 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
1794 // Only one pointer and no change in count so it must have the same id as before.
1795 uint32_t id = mLastTouch.pointers[0].id;
1796 mCurrentTouch.pointers[0].id = id;
1797 mCurrentTouch.idToIndex[id] = 0;
1798 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
1799 } else {
1800 // General case.
1801 // We build a heap of squared euclidean distances between current and last pointers
1802 // associated with the current and last pointer indices. Then, we find the best
1803 // match (by distance) for each current pointer.
1804 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
1805
1806 uint32_t heapSize = 0;
1807 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
1808 currentPointerIndex++) {
1809 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
1810 lastPointerIndex++) {
1811 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
1812 - mLastTouch.pointers[lastPointerIndex].x;
1813 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
1814 - mLastTouch.pointers[lastPointerIndex].y;
1815
1816 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
1817
1818 // Insert new element into the heap (sift up).
1819 heap[heapSize].currentPointerIndex = currentPointerIndex;
1820 heap[heapSize].lastPointerIndex = lastPointerIndex;
1821 heap[heapSize].distance = distance;
1822 heapSize += 1;
1823 }
1824 }
1825
1826 // Heapify
1827 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
1828 startIndex -= 1;
1829 for (uint32_t parentIndex = startIndex; ;) {
1830 uint32_t childIndex = parentIndex * 2 + 1;
1831 if (childIndex >= heapSize) {
1832 break;
1833 }
1834
1835 if (childIndex + 1 < heapSize
1836 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1837 childIndex += 1;
1838 }
1839
1840 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1841 break;
1842 }
1843
1844 swap(heap[parentIndex], heap[childIndex]);
1845 parentIndex = childIndex;
1846 }
1847 }
1848
1849#if DEBUG_POINTER_ASSIGNMENT
1850 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
1851 for (size_t i = 0; i < heapSize; i++) {
1852 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1853 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1854 heap[i].distance);
1855 }
1856#endif
1857
1858 // Pull matches out by increasing order of distance.
1859 // To avoid reassigning pointers that have already been matched, the loop keeps track
1860 // of which last and current pointers have been matched using the matchedXXXBits variables.
1861 // It also tracks the used pointer id bits.
1862 BitSet32 matchedLastBits(0);
1863 BitSet32 matchedCurrentBits(0);
1864 BitSet32 usedIdBits(0);
1865 bool first = true;
1866 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
1867 for (;;) {
1868 if (first) {
1869 // The first time through the loop, we just consume the root element of
1870 // the heap (the one with smallest distance).
1871 first = false;
1872 } else {
1873 // Previous iterations consumed the root element of the heap.
1874 // Pop root element off of the heap (sift down).
1875 heapSize -= 1;
1876 assert(heapSize > 0);
1877
1878 // Sift down.
1879 heap[0] = heap[heapSize];
1880 for (uint32_t parentIndex = 0; ;) {
1881 uint32_t childIndex = parentIndex * 2 + 1;
1882 if (childIndex >= heapSize) {
1883 break;
1884 }
1885
1886 if (childIndex + 1 < heapSize
1887 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1888 childIndex += 1;
1889 }
1890
1891 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1892 break;
1893 }
1894
1895 swap(heap[parentIndex], heap[childIndex]);
1896 parentIndex = childIndex;
1897 }
1898
1899#if DEBUG_POINTER_ASSIGNMENT
1900 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
1901 for (size_t i = 0; i < heapSize; i++) {
1902 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1903 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1904 heap[i].distance);
1905 }
1906#endif
1907 }
1908
1909 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
1910 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
1911
1912 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
1913 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
1914
1915 matchedCurrentBits.markBit(currentPointerIndex);
1916 matchedLastBits.markBit(lastPointerIndex);
1917
1918 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
1919 mCurrentTouch.pointers[currentPointerIndex].id = id;
1920 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1921 usedIdBits.markBit(id);
1922
1923#if DEBUG_POINTER_ASSIGNMENT
1924 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
1925 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
1926#endif
1927 break;
1928 }
1929 }
1930
1931 // Assign fresh ids to new pointers.
1932 if (currentPointerCount > lastPointerCount) {
1933 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
1934 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
1935 uint32_t id = usedIdBits.firstUnmarkedBit();
1936
1937 mCurrentTouch.pointers[currentPointerIndex].id = id;
1938 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1939 usedIdBits.markBit(id);
1940
1941#if DEBUG_POINTER_ASSIGNMENT
1942 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
1943 currentPointerIndex, id);
1944#endif
1945
1946 if (--i == 0) break; // done
1947 matchedCurrentBits.markBit(currentPointerIndex);
1948 }
1949 }
1950
1951 // Fix id bits.
1952 mCurrentTouch.idBits = usedIdBits;
1953 }
1954}
1955
1956/* Special hack for devices that have bad screen data: if one of the
1957 * points has moved more than a screen height from the last position,
1958 * then drop it. */
1959bool TouchInputMapper::applyBadTouchFilter() {
1960 // This hack requires valid axis parameters.
1961 if (! mAxes.y.valid) {
1962 return false;
1963 }
1964
1965 uint32_t pointerCount = mCurrentTouch.pointerCount;
1966
1967 // Nothing to do if there are no points.
1968 if (pointerCount == 0) {
1969 return false;
1970 }
1971
1972 // Don't do anything if a finger is going down or up. We run
1973 // here before assigning pointer IDs, so there isn't a good
1974 // way to do per-finger matching.
1975 if (pointerCount != mLastTouch.pointerCount) {
1976 return false;
1977 }
1978
1979 // We consider a single movement across more than a 7/16 of
1980 // the long size of the screen to be bad. This was a magic value
1981 // determined by looking at the maximum distance it is feasible
1982 // to actually move in one sample.
1983 int32_t maxDeltaY = mAxes.y.getRange() * 7 / 16;
1984
1985 // XXX The original code in InputDevice.java included commented out
1986 // code for testing the X axis. Note that when we drop a point
1987 // we don't actually restore the old X either. Strange.
1988 // The old code also tries to track when bad points were previously
1989 // detected but it turns out that due to the placement of a "break"
1990 // at the end of the loop, we never set mDroppedBadPoint to true
1991 // so it is effectively dead code.
1992 // Need to figure out if the old code is busted or just overcomplicated
1993 // but working as intended.
1994
1995 // Look through all new points and see if any are farther than
1996 // acceptable from all previous points.
1997 for (uint32_t i = pointerCount; i-- > 0; ) {
1998 int32_t y = mCurrentTouch.pointers[i].y;
1999 int32_t closestY = INT_MAX;
2000 int32_t closestDeltaY = 0;
2001
2002#if DEBUG_HACKS
2003 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2004#endif
2005
2006 for (uint32_t j = pointerCount; j-- > 0; ) {
2007 int32_t lastY = mLastTouch.pointers[j].y;
2008 int32_t deltaY = abs(y - lastY);
2009
2010#if DEBUG_HACKS
2011 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2012 j, lastY, deltaY);
2013#endif
2014
2015 if (deltaY < maxDeltaY) {
2016 goto SkipSufficientlyClosePoint;
2017 }
2018 if (deltaY < closestDeltaY) {
2019 closestDeltaY = deltaY;
2020 closestY = lastY;
2021 }
2022 }
2023
2024 // Must not have found a close enough match.
2025#if DEBUG_HACKS
2026 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2027 i, y, closestY, closestDeltaY, maxDeltaY);
2028#endif
2029
2030 mCurrentTouch.pointers[i].y = closestY;
2031 return true; // XXX original code only corrects one point
2032
2033 SkipSufficientlyClosePoint: ;
2034 }
2035
2036 // No change.
2037 return false;
2038}
2039
2040/* Special hack for devices that have bad screen data: drop points where
2041 * the coordinate value for one axis has jumped to the other pointer's location.
2042 */
2043bool TouchInputMapper::applyJumpyTouchFilter() {
2044 // This hack requires valid axis parameters.
2045 if (! mAxes.y.valid) {
2046 return false;
2047 }
2048
2049 uint32_t pointerCount = mCurrentTouch.pointerCount;
2050 if (mLastTouch.pointerCount != pointerCount) {
2051#if DEBUG_HACKS
2052 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2053 mLastTouch.pointerCount, pointerCount);
2054 for (uint32_t i = 0; i < pointerCount; i++) {
2055 LOGD(" Pointer %d (%d, %d)", i,
2056 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2057 }
2058#endif
2059
2060 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2061 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2062 // Just drop the first few events going from 1 to 2 pointers.
2063 // They're bad often enough that they're not worth considering.
2064 mCurrentTouch.pointerCount = 1;
2065 mJumpyTouchFilter.jumpyPointsDropped += 1;
2066
2067#if DEBUG_HACKS
2068 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2069#endif
2070 return true;
2071 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2072 // The event when we go from 2 -> 1 tends to be messed up too
2073 mCurrentTouch.pointerCount = 2;
2074 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2075 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2076 mJumpyTouchFilter.jumpyPointsDropped += 1;
2077
2078#if DEBUG_HACKS
2079 for (int32_t i = 0; i < 2; i++) {
2080 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2081 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2082 }
2083#endif
2084 return true;
2085 }
2086 }
2087 // Reset jumpy points dropped on other transitions or if limit exceeded.
2088 mJumpyTouchFilter.jumpyPointsDropped = 0;
2089
2090#if DEBUG_HACKS
2091 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2092#endif
2093 return false;
2094 }
2095
2096 // We have the same number of pointers as last time.
2097 // A 'jumpy' point is one where the coordinate value for one axis
2098 // has jumped to the other pointer's location. No need to do anything
2099 // else if we only have one pointer.
2100 if (pointerCount < 2) {
2101 return false;
2102 }
2103
2104 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
2105 int jumpyEpsilon = mAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
2106
2107 // We only replace the single worst jumpy point as characterized by pointer distance
2108 // in a single axis.
2109 int32_t badPointerIndex = -1;
2110 int32_t badPointerReplacementIndex = -1;
2111 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2112
2113 for (uint32_t i = pointerCount; i-- > 0; ) {
2114 int32_t x = mCurrentTouch.pointers[i].x;
2115 int32_t y = mCurrentTouch.pointers[i].y;
2116
2117#if DEBUG_HACKS
2118 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2119#endif
2120
2121 // Check if a touch point is too close to another's coordinates
2122 bool dropX = false, dropY = false;
2123 for (uint32_t j = 0; j < pointerCount; j++) {
2124 if (i == j) {
2125 continue;
2126 }
2127
2128 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2129 dropX = true;
2130 break;
2131 }
2132
2133 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2134 dropY = true;
2135 break;
2136 }
2137 }
2138 if (! dropX && ! dropY) {
2139 continue; // not jumpy
2140 }
2141
2142 // Find a replacement candidate by comparing with older points on the
2143 // complementary (non-jumpy) axis.
2144 int32_t distance = INT_MIN; // distance to be corrected
2145 int32_t replacementIndex = -1;
2146
2147 if (dropX) {
2148 // X looks too close. Find an older replacement point with a close Y.
2149 int32_t smallestDeltaY = INT_MAX;
2150 for (uint32_t j = 0; j < pointerCount; j++) {
2151 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2152 if (deltaY < smallestDeltaY) {
2153 smallestDeltaY = deltaY;
2154 replacementIndex = j;
2155 }
2156 }
2157 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2158 } else {
2159 // Y looks too close. Find an older replacement point with a close X.
2160 int32_t smallestDeltaX = INT_MAX;
2161 for (uint32_t j = 0; j < pointerCount; j++) {
2162 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2163 if (deltaX < smallestDeltaX) {
2164 smallestDeltaX = deltaX;
2165 replacementIndex = j;
2166 }
2167 }
2168 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2169 }
2170
2171 // If replacing this pointer would correct a worse error than the previous ones
2172 // considered, then use this replacement instead.
2173 if (distance > badPointerDistance) {
2174 badPointerIndex = i;
2175 badPointerReplacementIndex = replacementIndex;
2176 badPointerDistance = distance;
2177 }
2178 }
2179
2180 // Correct the jumpy pointer if one was found.
2181 if (badPointerIndex >= 0) {
2182#if DEBUG_HACKS
2183 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2184 badPointerIndex,
2185 mLastTouch.pointers[badPointerReplacementIndex].x,
2186 mLastTouch.pointers[badPointerReplacementIndex].y);
2187#endif
2188
2189 mCurrentTouch.pointers[badPointerIndex].x =
2190 mLastTouch.pointers[badPointerReplacementIndex].x;
2191 mCurrentTouch.pointers[badPointerIndex].y =
2192 mLastTouch.pointers[badPointerReplacementIndex].y;
2193 mJumpyTouchFilter.jumpyPointsDropped += 1;
2194 return true;
2195 }
2196 }
2197
2198 mJumpyTouchFilter.jumpyPointsDropped = 0;
2199 return false;
2200}
2201
2202/* Special hack for devices that have bad screen data: aggregate and
2203 * compute averages of the coordinate data, to reduce the amount of
2204 * jitter seen by applications. */
2205void TouchInputMapper::applyAveragingTouchFilter() {
2206 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2207 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2208 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2209 int32_t y = mCurrentTouch.pointers[currentIndex].y;
2210 int32_t pressure = mCurrentTouch.pointers[currentIndex].pressure;
2211
2212 if (mLastTouch.idBits.hasBit(id)) {
2213 // Pointer was down before and is still down now.
2214 // Compute average over history trace.
2215 uint32_t start = mAveragingTouchFilter.historyStart[id];
2216 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2217
2218 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2219 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2220 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2221
2222#if DEBUG_HACKS
2223 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2224 id, distance);
2225#endif
2226
2227 if (distance < AVERAGING_DISTANCE_LIMIT) {
2228 // Increment end index in preparation for recording new historical data.
2229 end += 1;
2230 if (end > AVERAGING_HISTORY_SIZE) {
2231 end = 0;
2232 }
2233
2234 // If the end index has looped back to the start index then we have filled
2235 // the historical trace up to the desired size so we drop the historical
2236 // data at the start of the trace.
2237 if (end == start) {
2238 start += 1;
2239 if (start > AVERAGING_HISTORY_SIZE) {
2240 start = 0;
2241 }
2242 }
2243
2244 // Add the raw data to the historical trace.
2245 mAveragingTouchFilter.historyStart[id] = start;
2246 mAveragingTouchFilter.historyEnd[id] = end;
2247 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2248 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2249 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2250
2251 // Average over all historical positions in the trace by total pressure.
2252 int32_t averagedX = 0;
2253 int32_t averagedY = 0;
2254 int32_t totalPressure = 0;
2255 for (;;) {
2256 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2257 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2258 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2259 .pointers[id].pressure;
2260
2261 averagedX += historicalX * historicalPressure;
2262 averagedY += historicalY * historicalPressure;
2263 totalPressure += historicalPressure;
2264
2265 if (start == end) {
2266 break;
2267 }
2268
2269 start += 1;
2270 if (start > AVERAGING_HISTORY_SIZE) {
2271 start = 0;
2272 }
2273 }
2274
2275 averagedX /= totalPressure;
2276 averagedY /= totalPressure;
2277
2278#if DEBUG_HACKS
2279 LOGD("AveragingTouchFilter: Pointer id %d - "
2280 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2281 averagedX, averagedY);
2282#endif
2283
2284 mCurrentTouch.pointers[currentIndex].x = averagedX;
2285 mCurrentTouch.pointers[currentIndex].y = averagedY;
2286 } else {
2287#if DEBUG_HACKS
2288 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2289#endif
2290 }
2291 } else {
2292#if DEBUG_HACKS
2293 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2294#endif
2295 }
2296
2297 // Reset pointer history.
2298 mAveragingTouchFilter.historyStart[id] = 0;
2299 mAveragingTouchFilter.historyEnd[id] = 0;
2300 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2301 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2302 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
2303 }
2304}
2305
2306int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002307 { // acquire lock
2308 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002309
Jeff Brown6328cdc2010-07-29 18:18:33 -07002310 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002311 return AKEY_STATE_VIRTUAL;
2312 }
2313
Jeff Brown6328cdc2010-07-29 18:18:33 -07002314 size_t numVirtualKeys = mLocked.virtualKeys.size();
2315 for (size_t i = 0; i < numVirtualKeys; i++) {
2316 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002317 if (virtualKey.keyCode == keyCode) {
2318 return AKEY_STATE_UP;
2319 }
2320 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002321 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002322
2323 return AKEY_STATE_UNKNOWN;
2324}
2325
2326int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002327 { // acquire lock
2328 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002329
Jeff Brown6328cdc2010-07-29 18:18:33 -07002330 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002331 return AKEY_STATE_VIRTUAL;
2332 }
2333
Jeff Brown6328cdc2010-07-29 18:18:33 -07002334 size_t numVirtualKeys = mLocked.virtualKeys.size();
2335 for (size_t i = 0; i < numVirtualKeys; i++) {
2336 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002337 if (virtualKey.scanCode == scanCode) {
2338 return AKEY_STATE_UP;
2339 }
2340 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002341 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002342
2343 return AKEY_STATE_UNKNOWN;
2344}
2345
2346bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2347 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002348 { // acquire lock
2349 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002350
Jeff Brown6328cdc2010-07-29 18:18:33 -07002351 size_t numVirtualKeys = mLocked.virtualKeys.size();
2352 for (size_t i = 0; i < numVirtualKeys; i++) {
2353 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002354
2355 for (size_t i = 0; i < numCodes; i++) {
2356 if (virtualKey.keyCode == keyCodes[i]) {
2357 outFlags[i] = 1;
2358 }
2359 }
2360 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002361 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002362
2363 return true;
2364}
2365
2366
2367// --- SingleTouchInputMapper ---
2368
2369SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2370 TouchInputMapper(device, associatedDisplayId) {
2371 initialize();
2372}
2373
2374SingleTouchInputMapper::~SingleTouchInputMapper() {
2375}
2376
2377void SingleTouchInputMapper::initialize() {
2378 mAccumulator.clear();
2379
2380 mDown = false;
2381 mX = 0;
2382 mY = 0;
2383 mPressure = 0;
2384 mSize = 0;
2385}
2386
2387void SingleTouchInputMapper::reset() {
2388 TouchInputMapper::reset();
2389
Jeff Brown6d0fec22010-07-23 21:28:06 -07002390 initialize();
2391 }
2392
2393void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
2394 switch (rawEvent->type) {
2395 case EV_KEY:
2396 switch (rawEvent->scanCode) {
2397 case BTN_TOUCH:
2398 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
2399 mAccumulator.btnTouch = rawEvent->value != 0;
2400
2401 sync(rawEvent->when);
2402 mAccumulator.clear();
2403 break;
2404 }
2405 break;
2406
2407 case EV_ABS:
2408 switch (rawEvent->scanCode) {
2409 case ABS_X:
2410 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
2411 mAccumulator.absX = rawEvent->value;
2412 break;
2413 case ABS_Y:
2414 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
2415 mAccumulator.absY = rawEvent->value;
2416 break;
2417 case ABS_PRESSURE:
2418 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
2419 mAccumulator.absPressure = rawEvent->value;
2420 break;
2421 case ABS_TOOL_WIDTH:
2422 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
2423 mAccumulator.absToolWidth = rawEvent->value;
2424 break;
2425 }
2426 break;
2427
2428 case EV_SYN:
2429 switch (rawEvent->scanCode) {
2430 case SYN_REPORT:
2431 if (mAccumulator.isDirty()) {
2432 sync(rawEvent->when);
2433 mAccumulator.clear();
2434 }
2435 break;
2436 }
2437 break;
2438 }
2439}
2440
2441void SingleTouchInputMapper::sync(nsecs_t when) {
2442 /* Update device state */
2443
2444 uint32_t fields = mAccumulator.fields;
2445
2446 if (fields & Accumulator::FIELD_BTN_TOUCH) {
2447 mDown = mAccumulator.btnTouch;
2448 }
2449
2450 if (fields & Accumulator::FIELD_ABS_X) {
2451 mX = mAccumulator.absX;
2452 }
2453
2454 if (fields & Accumulator::FIELD_ABS_Y) {
2455 mY = mAccumulator.absY;
2456 }
2457
2458 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
2459 mPressure = mAccumulator.absPressure;
2460 }
2461
2462 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
2463 mSize = mAccumulator.absToolWidth;
2464 }
2465
2466 mCurrentTouch.clear();
2467
2468 if (mDown) {
2469 mCurrentTouch.pointerCount = 1;
2470 mCurrentTouch.pointers[0].id = 0;
2471 mCurrentTouch.pointers[0].x = mX;
2472 mCurrentTouch.pointers[0].y = mY;
2473 mCurrentTouch.pointers[0].pressure = mPressure;
2474 mCurrentTouch.pointers[0].size = mSize;
2475 mCurrentTouch.pointers[0].touchMajor = mPressure;
2476 mCurrentTouch.pointers[0].touchMinor = mPressure;
2477 mCurrentTouch.pointers[0].toolMajor = mSize;
2478 mCurrentTouch.pointers[0].toolMinor = mSize;
2479 mCurrentTouch.pointers[0].orientation = 0;
2480 mCurrentTouch.idToIndex[0] = 0;
2481 mCurrentTouch.idBits.markBit(0);
2482 }
2483
2484 syncTouch(when, true);
2485}
2486
2487void SingleTouchInputMapper::configureAxes() {
2488 TouchInputMapper::configureAxes();
2489
2490 // The axes are aliased to take into account the manner in which they are presented
2491 // as part of the TouchData during the sync.
2492 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mAxes.x);
2493 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mAxes.y);
2494 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure);
2495 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size);
2496
2497 mAxes.touchMajor = mAxes.pressure;
2498 mAxes.touchMinor = mAxes.pressure;
2499 mAxes.toolMajor = mAxes.size;
2500 mAxes.toolMinor = mAxes.size;
2501}
2502
2503
2504// --- MultiTouchInputMapper ---
2505
2506MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2507 TouchInputMapper(device, associatedDisplayId) {
2508 initialize();
2509}
2510
2511MultiTouchInputMapper::~MultiTouchInputMapper() {
2512}
2513
2514void MultiTouchInputMapper::initialize() {
2515 mAccumulator.clear();
2516}
2517
2518void MultiTouchInputMapper::reset() {
2519 TouchInputMapper::reset();
2520
Jeff Brown6d0fec22010-07-23 21:28:06 -07002521 initialize();
2522}
2523
2524void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
2525 switch (rawEvent->type) {
2526 case EV_ABS: {
2527 uint32_t pointerIndex = mAccumulator.pointerCount;
2528 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
2529
2530 switch (rawEvent->scanCode) {
2531 case ABS_MT_POSITION_X:
2532 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
2533 pointer->absMTPositionX = rawEvent->value;
2534 break;
2535 case ABS_MT_POSITION_Y:
2536 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
2537 pointer->absMTPositionY = rawEvent->value;
2538 break;
2539 case ABS_MT_TOUCH_MAJOR:
2540 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
2541 pointer->absMTTouchMajor = rawEvent->value;
2542 break;
2543 case ABS_MT_TOUCH_MINOR:
2544 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
2545 pointer->absMTTouchMinor = rawEvent->value;
2546 break;
2547 case ABS_MT_WIDTH_MAJOR:
2548 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
2549 pointer->absMTWidthMajor = rawEvent->value;
2550 break;
2551 case ABS_MT_WIDTH_MINOR:
2552 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
2553 pointer->absMTWidthMinor = rawEvent->value;
2554 break;
2555 case ABS_MT_ORIENTATION:
2556 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
2557 pointer->absMTOrientation = rawEvent->value;
2558 break;
2559 case ABS_MT_TRACKING_ID:
2560 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
2561 pointer->absMTTrackingId = rawEvent->value;
2562 break;
2563 }
2564 break;
2565 }
2566
2567 case EV_SYN:
2568 switch (rawEvent->scanCode) {
2569 case SYN_MT_REPORT: {
2570 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
2571 uint32_t pointerIndex = mAccumulator.pointerCount;
2572
2573 if (mAccumulator.pointers[pointerIndex].fields) {
2574 if (pointerIndex == MAX_POINTERS) {
2575 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
2576 MAX_POINTERS);
2577 } else {
2578 pointerIndex += 1;
2579 mAccumulator.pointerCount = pointerIndex;
2580 }
2581 }
2582
2583 mAccumulator.pointers[pointerIndex].clear();
2584 break;
2585 }
2586
2587 case SYN_REPORT:
2588 if (mAccumulator.isDirty()) {
2589 sync(rawEvent->when);
2590 mAccumulator.clear();
2591 }
2592 break;
2593 }
2594 break;
2595 }
2596}
2597
2598void MultiTouchInputMapper::sync(nsecs_t when) {
2599 static const uint32_t REQUIRED_FIELDS =
2600 Accumulator::FIELD_ABS_MT_POSITION_X
2601 | Accumulator::FIELD_ABS_MT_POSITION_Y
2602 | Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
2603 | Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002604
2605 /* Update device state */
2606
Jeff Brown6d0fec22010-07-23 21:28:06 -07002607 uint32_t inCount = mAccumulator.pointerCount;
2608 uint32_t outCount = 0;
2609 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002610
Jeff Brown6d0fec22010-07-23 21:28:06 -07002611 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002612
Jeff Brown6d0fec22010-07-23 21:28:06 -07002613 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
2614 uint32_t fields = mAccumulator.pointers[inIndex].fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002615
Jeff Brown6d0fec22010-07-23 21:28:06 -07002616 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
2617#if DEBUG_POINTERS
2618 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
2619 inIndex, fields);
2620 continue;
2621#endif
Jeff Brown46b9ac02010-04-22 18:58:52 -07002622 }
2623
Jeff Brown6d0fec22010-07-23 21:28:06 -07002624 if (mAccumulator.pointers[inIndex].absMTTouchMajor <= 0) {
2625 // Pointer is not down. Drop it.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002626 continue;
2627 }
2628
Jeff Brown6d0fec22010-07-23 21:28:06 -07002629 mCurrentTouch.pointers[outCount].x = mAccumulator.pointers[inIndex].absMTPositionX;
2630 mCurrentTouch.pointers[outCount].y = mAccumulator.pointers[inIndex].absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002631
Jeff Brown6d0fec22010-07-23 21:28:06 -07002632 mCurrentTouch.pointers[outCount].touchMajor =
2633 mAccumulator.pointers[inIndex].absMTTouchMajor;
2634 mCurrentTouch.pointers[outCount].touchMinor =
2635 (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
2636 ? mAccumulator.pointers[inIndex].absMTTouchMinor
2637 : mAccumulator.pointers[inIndex].absMTTouchMajor;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002638
Jeff Brown6d0fec22010-07-23 21:28:06 -07002639 mCurrentTouch.pointers[outCount].toolMajor =
2640 mAccumulator.pointers[inIndex].absMTWidthMajor;
2641 mCurrentTouch.pointers[outCount].toolMinor =
2642 (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
2643 ? mAccumulator.pointers[inIndex].absMTWidthMinor
2644 : mAccumulator.pointers[inIndex].absMTWidthMajor;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002645
Jeff Brown6d0fec22010-07-23 21:28:06 -07002646 mCurrentTouch.pointers[outCount].orientation =
2647 (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
2648 ? mAccumulator.pointers[inIndex].absMTOrientation : 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002649
Jeff Brown6d0fec22010-07-23 21:28:06 -07002650 // Derive an approximation of pressure and size.
2651 // FIXME assignment of pressure may be incorrect, probably better to let
2652 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
2653 // isn't quite right either. Should be using touch for that.
2654 mCurrentTouch.pointers[outCount].pressure = mAccumulator.pointers[inIndex].absMTTouchMajor;
2655 mCurrentTouch.pointers[outCount].size = mAccumulator.pointers[inIndex].absMTWidthMajor;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002656
Jeff Brown6d0fec22010-07-23 21:28:06 -07002657 if (havePointerIds) {
2658 if (fields & Accumulator::
2659 FIELD_ABS_MT_TRACKING_ID) {
2660 uint32_t id = uint32_t(mAccumulator.pointers[inIndex].absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002661
Jeff Brown6d0fec22010-07-23 21:28:06 -07002662 if (id > MAX_POINTER_ID) {
2663#if DEBUG_POINTERS
2664 LOGD("Pointers: Ignoring driver provided pointer id %d because "
2665 "it is larger than max supported id %d for optimizations",
2666 id, MAX_POINTER_ID);
2667#endif
2668 havePointerIds = false;
2669 }
2670 else {
2671 mCurrentTouch.pointers[outCount].id = id;
2672 mCurrentTouch.idToIndex[id] = outCount;
2673 mCurrentTouch.idBits.markBit(id);
2674 }
2675 } else {
2676 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002677 }
2678 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002679
Jeff Brown6d0fec22010-07-23 21:28:06 -07002680 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002681 }
2682
Jeff Brown6d0fec22010-07-23 21:28:06 -07002683 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002684
Jeff Brown6d0fec22010-07-23 21:28:06 -07002685 syncTouch(when, havePointerIds);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002686}
2687
Jeff Brown6d0fec22010-07-23 21:28:06 -07002688void MultiTouchInputMapper::configureAxes() {
2689 TouchInputMapper::configureAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002690
Jeff Brown6d0fec22010-07-23 21:28:06 -07002691 // The axes are aliased to take into account the manner in which they are presented
2692 // as part of the TouchData during the sync.
2693 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mAxes.x);
2694 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mAxes.y);
2695 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mAxes.touchMajor);
2696 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mAxes.touchMinor);
2697 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor);
2698 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor);
2699 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation);
Jeff Brown9c3cda02010-06-15 01:31:58 -07002700
Jeff Brown6d0fec22010-07-23 21:28:06 -07002701 if (! mAxes.touchMinor.valid) {
2702 mAxes.touchMinor = mAxes.touchMajor;
Jeff Brown9c3cda02010-06-15 01:31:58 -07002703 }
2704
Jeff Brown6d0fec22010-07-23 21:28:06 -07002705 if (! mAxes.toolMinor.valid) {
2706 mAxes.toolMinor = mAxes.toolMajor;
2707 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07002708
Jeff Brown6d0fec22010-07-23 21:28:06 -07002709 mAxes.pressure = mAxes.touchMajor;
2710 mAxes.size = mAxes.toolMajor;
Jeff Brown9c3cda02010-06-15 01:31:58 -07002711}
2712
Jeff Brown46b9ac02010-04-22 18:58:52 -07002713
2714} // namespace android