blob: 6f042ec7e8e406f22150aa59d6215fa3e7360d2c [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brownf4a4ec22010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Browne839a582010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Browne839a582010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
Jeff Brown5c1ed842010-07-14 18:48:53 -070032#include <math.h>
Jeff Browne839a582010-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 Brownf4a4ec22010-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 Browne839a582010-04-22 18:58:52 -070056int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
57 int32_t mask;
58 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070059 case AKEYCODE_ALT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070060 mask = AMETA_ALT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070061 break;
Jeff Brown8575a872010-06-30 16:10:35 -070062 case AKEYCODE_ALT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070063 mask = AMETA_ALT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070064 break;
Jeff Brown8575a872010-06-30 16:10:35 -070065 case AKEYCODE_SHIFT_LEFT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070066 mask = AMETA_SHIFT_LEFT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070067 break;
Jeff Brown8575a872010-06-30 16:10:35 -070068 case AKEYCODE_SHIFT_RIGHT:
Jeff Brown5c1ed842010-07-14 18:48:53 -070069 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070070 break;
Jeff Brown8575a872010-06-30 16:10:35 -070071 case AKEYCODE_SYM:
Jeff Brown5c1ed842010-07-14 18:48:53 -070072 mask = AMETA_SYM_ON;
Jeff Browne839a582010-04-22 18:58:52 -070073 break;
74 default:
75 return oldMetaState;
76 }
77
78 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brown5c1ed842010-07-14 18:48:53 -070079 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Browne839a582010-04-22 18:58:52 -070080
Jeff Brown5c1ed842010-07-14 18:48:53 -070081 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
82 newMetaState |= AMETA_ALT_ON;
Jeff Browne839a582010-04-22 18:58:52 -070083 }
84
Jeff Brown5c1ed842010-07-14 18:48:53 -070085 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
86 newMetaState |= AMETA_SHIFT_ON;
Jeff Browne839a582010-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 Brown8575a872010-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 Browne839a582010-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 Brown54bc2812010-06-15 01:31:58 -0700104 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-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 Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700118
Jeff Browne839a582010-04-22 18:58:52 -0700119// --- InputReader ---
120
121InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700122 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700123 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Browne57e8952010-07-23 21:28:06 -0700124 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
125 mGlobalMetaState(0) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700126 configureExcludedDevices();
Jeff Browne57e8952010-07-23 21:28:06 -0700127 updateGlobalMetaState();
128 updateInputConfiguration();
Jeff Browne839a582010-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 Browne57e8952010-07-23 21:28:06 -0700139 mEventHub->getEvent(& rawEvent);
Jeff Browne839a582010-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 Browne57e8952010-07-23 21:28:06 -0700153 addDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700154 break;
155
156 case EventHubInterface::DEVICE_REMOVED:
Jeff Browne57e8952010-07-23 21:28:06 -0700157 removeDevice(rawEvent->when, rawEvent->deviceId);
Jeff Browne839a582010-04-22 18:58:52 -0700158 break;
159
Jeff Browne57e8952010-07-23 21:28:06 -0700160 default:
161 consumeEvent(rawEvent);
Jeff Browne839a582010-04-22 18:58:52 -0700162 break;
163 }
164}
165
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700187 return;
188 }
189
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700199}
200
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700233}
234
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700237
Jeff Browne57e8952010-07-23 21:28:06 -0700238 const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
Jeff Browne839a582010-04-22 18:58:52 -0700239
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700374 }
375 }
Jeff Browne57e8952010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Browne839a582010-04-22 18:58:52 -0700377
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700399 }
400
Jeff Browne57e8952010-07-23 21:28:06 -0700401 InputDevice* device = mDevices.valueAt(deviceIndex);
402 if (device->isIgnored()) {
403 return NAME_NOT_FOUND;
Jeff Browne839a582010-04-22 18:58:52 -0700404 }
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700547 }
548}
549
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700557
Jeff Browne57e8952010-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 Browne839a582010-04-22 18:58:52 -0700565
Jeff Browne57e8952010-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 Brownb51719b2010-07-29 18:18:33 -0700716 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -0700717}
718
719KeyboardInputMapper::~KeyboardInputMapper() {
720}
721
Jeff Brownb51719b2010-07-29 18:18:33 -0700722void KeyboardInputMapper::initializeLocked() {
723 mLocked.metaState = AMETA_NONE;
724 mLocked.downTime = 0;
Jeff Browne57e8952010-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 Brownb51719b2010-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 Browne57e8952010-07-23 21:28:06 -0700754 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700755 processKey(when, false, keyCode, scanCode, 0);
Jeff Browne57e8952010-07-23 21:28:06 -0700756 }
757
758 InputMapper::reset();
Jeff Browne57e8952010-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 Brownb51719b2010-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 Browne57e8952010-07-23 21:28:06 -0700800 }
801
Jeff Brownb51719b2010-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 Browne57e8952010-07-23 21:28:06 -0700830 }
831
Jeff Brownb51719b2010-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 Browne57e8952010-07-23 21:28:06 -0700837 }
Jeff Brown8575a872010-06-30 16:10:35 -0700838
Jeff Brownb51719b2010-07-29 18:18:33 -0700839 downTime = mLocked.downTime;
840 } // release lock
841
842 if (metaStateChanged) {
Jeff Browne57e8952010-07-23 21:28:06 -0700843 getContext()->updateGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -0700844 }
845
Jeff Brownb51719b2010-07-29 18:18:33 -0700846 applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
847}
Jeff Browne839a582010-04-22 18:58:52 -0700848
Jeff Brownb51719b2010-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 Browne57e8952010-07-23 21:28:06 -0700851 int32_t policyActions = getPolicy()->interceptKey(when,
852 getDeviceId(), down, keyCode, scanCode, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700853
Jeff Browne57e8952010-07-23 21:28:06 -0700854 if (! applyStandardPolicyActions(when, policyActions)) {
Jeff Browne839a582010-04-22 18:58:52 -0700855 return; // event dropped
856 }
857
Jeff Brownb51719b2010-07-29 18:18:33 -0700858 int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
Jeff Brown5c1ed842010-07-14 18:48:53 -0700859 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Browne57e8952010-07-23 21:28:06 -0700860 if (policyFlags & POLICY_FLAG_WOKE_HERE) {
Jeff Brown5c1ed842010-07-14 18:48:53 -0700861 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Browne839a582010-04-22 18:58:52 -0700862 }
863
Jeff Browne57e8952010-07-23 21:28:06 -0700864 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brownb51719b2010-07-29 18:18:33 -0700865 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
Jeff Browne839a582010-04-22 18:58:52 -0700866}
867
Jeff Brownb51719b2010-07-29 18:18:33 -0700868ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
869 size_t n = mLocked.keyDowns.size();
Jeff Browne57e8952010-07-23 21:28:06 -0700870 for (size_t i = 0; i < n; i++) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700871 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -0700872 return i;
873 }
874 }
875 return -1;
Jeff Browne839a582010-04-22 18:58:52 -0700876}
877
Jeff Browne57e8952010-07-23 21:28:06 -0700878int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
879 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
880}
Jeff Browne839a582010-04-22 18:58:52 -0700881
Jeff Browne57e8952010-07-23 21:28:06 -0700882int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
883 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
884}
Jeff Browne839a582010-04-22 18:58:52 -0700885
Jeff Browne57e8952010-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 Brownb51719b2010-07-29 18:18:33 -0700892 { // acquire lock
893 AutoMutex _l(mLock);
894 return mLocked.metaState;
895 } // release lock
Jeff Browne57e8952010-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 Brownb51719b2010-07-29 18:18:33 -0700908 initializeLocked();
Jeff Browne57e8952010-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 Brownb51719b2010-07-29 18:18:33 -0700925void TrackballInputMapper::initializeLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -0700926 mAccumulator.clear();
927
Jeff Brownb51719b2010-07-29 18:18:33 -0700928 mLocked.down = false;
929 mLocked.downTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -0700930}
931
932void TrackballInputMapper::reset() {
Jeff Brownb51719b2010-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 Browne57e8952010-07-23 21:28:06 -0700944 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownb51719b2010-07-29 18:18:33 -0700945 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Browne57e8952010-07-23 21:28:06 -0700946 mAccumulator.btnMouse = false;
947 sync(when);
Jeff Browne839a582010-04-22 18:58:52 -0700948 }
949
Jeff Browne57e8952010-07-23 21:28:06 -0700950 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700951}
Jeff Browne839a582010-04-22 18:58:52 -0700952
Jeff Browne57e8952010-07-23 21:28:06 -0700953void TrackballInputMapper::process(const RawEvent* rawEvent) {
954 switch (rawEvent->type) {
955 case EV_KEY:
956 switch (rawEvent->scanCode) {
957 case BTN_MOUSE:
958 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
959 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -0700960 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
961 // we need to ensure that we report the up/down promptly.
Jeff Browne57e8952010-07-23 21:28:06 -0700962 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -0700963 break;
Jeff Browne839a582010-04-22 18:58:52 -0700964 }
Jeff Browne57e8952010-07-23 21:28:06 -0700965 break;
Jeff Browne839a582010-04-22 18:58:52 -0700966
Jeff Browne57e8952010-07-23 21:28:06 -0700967 case EV_REL:
968 switch (rawEvent->scanCode) {
969 case REL_X:
970 mAccumulator.fields |= Accumulator::FIELD_REL_X;
971 mAccumulator.relX = rawEvent->value;
972 break;
973 case REL_Y:
974 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
975 mAccumulator.relY = rawEvent->value;
976 break;
Jeff Browne839a582010-04-22 18:58:52 -0700977 }
Jeff Browne57e8952010-07-23 21:28:06 -0700978 break;
Jeff Browne839a582010-04-22 18:58:52 -0700979
Jeff Browne57e8952010-07-23 21:28:06 -0700980 case EV_SYN:
981 switch (rawEvent->scanCode) {
982 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -0700983 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -0700984 break;
Jeff Browne839a582010-04-22 18:58:52 -0700985 }
Jeff Browne57e8952010-07-23 21:28:06 -0700986 break;
Jeff Browne839a582010-04-22 18:58:52 -0700987 }
Jeff Browne839a582010-04-22 18:58:52 -0700988}
989
Jeff Browne57e8952010-07-23 21:28:06 -0700990void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownd64c8552010-08-17 20:38:35 -0700991 uint32_t fields = mAccumulator.fields;
992 if (fields == 0) {
993 return; // no new state changes, so nothing to do
994 }
995
Jeff Brownb51719b2010-07-29 18:18:33 -0700996 int motionEventAction;
997 PointerCoords pointerCoords;
998 nsecs_t downTime;
999 { // acquire lock
1000 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001001
Jeff Brownb51719b2010-07-29 18:18:33 -07001002 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 Browne57e8952010-07-23 21:28:06 -07001011 }
Jeff Browne839a582010-04-22 18:58:52 -07001012
Jeff Brownb51719b2010-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 Browne839a582010-04-22 18:58:52 -07001016
Jeff Brownb51719b2010-07-29 18:18:33 -07001017 if (downChanged) {
1018 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browne57e8952010-07-23 21:28:06 -07001019 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001020 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001021 }
Jeff Browne839a582010-04-22 18:58:52 -07001022
Jeff Brownb51719b2010-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 Browne839a582010-04-22 18:58:52 -07001032
Jeff Brownb51719b2010-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);
Jeff Brownd64c8552010-08-17 20:38:35 -07001064
1065 mAccumulator.clear();
Jeff Brownb51719b2010-07-29 18:18:33 -07001066}
1067
1068void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1069 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001070 uint32_t policyFlags = 0;
1071 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1072
1073 if (! applyStandardPolicyActions(when, policyActions)) {
1074 return; // event dropped
1075 }
1076
Jeff Browne57e8952010-07-23 21:28:06 -07001077 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001078 int32_t pointerId = 0;
1079
Jeff Browne57e8952010-07-23 21:28:06 -07001080 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
1081 motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001082 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001083}
1084
Jeff Brown8d4dfd22010-08-10 15:47:53 -07001085int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1086 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1087 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1088 } else {
1089 return AKEY_STATE_UNKNOWN;
1090 }
1091}
1092
Jeff Browne57e8952010-07-23 21:28:06 -07001093
1094// --- TouchInputMapper ---
1095
1096TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001097 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1098 mLocked.surfaceOrientation = -1;
1099 mLocked.surfaceWidth = -1;
1100 mLocked.surfaceHeight = -1;
1101
1102 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001103}
1104
1105TouchInputMapper::~TouchInputMapper() {
1106}
1107
1108uint32_t TouchInputMapper::getSources() {
1109 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1110}
1111
1112void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1113 InputMapper::populateDeviceInfo(info);
1114
Jeff Brownb51719b2010-07-29 18:18:33 -07001115 { // acquire lock
1116 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001117
Jeff Brownb51719b2010-07-29 18:18:33 -07001118 // Ensure surface information is up to date so that orientation changes are
1119 // noticed immediately.
1120 configureSurfaceLocked();
1121
1122 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1123 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
1124 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, mLocked.orientedRanges.pressure);
1125 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE, mLocked.orientedRanges.size);
1126 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR, mLocked.orientedRanges.touchMajor);
1127 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR, mLocked.orientedRanges.touchMinor);
1128 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR, mLocked.orientedRanges.toolMajor);
1129 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR, mLocked.orientedRanges.toolMinor);
1130 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION, mLocked.orientedRanges.orientation);
1131 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001132}
1133
Jeff Brownb51719b2010-07-29 18:18:33 -07001134void TouchInputMapper::initializeLocked() {
1135 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001136 mLastTouch.clear();
1137 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001138
1139 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1140 mAveragingTouchFilter.historyStart[i] = 0;
1141 mAveragingTouchFilter.historyEnd[i] = 0;
1142 }
1143
1144 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001145
1146 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07001147}
1148
1149void TouchInputMapper::configure() {
1150 InputMapper::configure();
1151
1152 // Configure basic parameters.
1153 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1154 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1155 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1156
1157 // Configure absolute axis information.
1158 configureAxes();
1159
Jeff Brownb51719b2010-07-29 18:18:33 -07001160 { // acquire lock
1161 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001162
Jeff Brownb51719b2010-07-29 18:18:33 -07001163 // Configure pressure factors.
1164 if (mAxes.pressure.valid) {
1165 mLocked.pressureOrigin = mAxes.pressure.minValue;
1166 mLocked.pressureScale = 1.0f / mAxes.pressure.getRange();
1167 } else {
1168 mLocked.pressureOrigin = 0;
1169 mLocked.pressureScale = 1.0f;
1170 }
Jeff Browne57e8952010-07-23 21:28:06 -07001171
Jeff Brownb51719b2010-07-29 18:18:33 -07001172 mLocked.orientedRanges.pressure.min = 0.0f;
1173 mLocked.orientedRanges.pressure.max = 1.0f;
1174 mLocked.orientedRanges.pressure.flat = 0.0f;
1175 mLocked.orientedRanges.pressure.fuzz = mLocked.pressureScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001176
Jeff Brownb51719b2010-07-29 18:18:33 -07001177 // Configure size factors.
1178 if (mAxes.size.valid) {
1179 mLocked.sizeOrigin = mAxes.size.minValue;
1180 mLocked.sizeScale = 1.0f / mAxes.size.getRange();
1181 } else {
1182 mLocked.sizeOrigin = 0;
1183 mLocked.sizeScale = 1.0f;
1184 }
Jeff Browne57e8952010-07-23 21:28:06 -07001185
Jeff Brownb51719b2010-07-29 18:18:33 -07001186 mLocked.orientedRanges.size.min = 0.0f;
1187 mLocked.orientedRanges.size.max = 1.0f;
1188 mLocked.orientedRanges.size.flat = 0.0f;
1189 mLocked.orientedRanges.size.fuzz = mLocked.sizeScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001190
Jeff Brownb51719b2010-07-29 18:18:33 -07001191 // Configure orientation factors.
1192 if (mAxes.orientation.valid && mAxes.orientation.maxValue > 0) {
1193 mLocked.orientationScale = float(M_PI_2) / mAxes.orientation.maxValue;
1194 } else {
1195 mLocked.orientationScale = 0.0f;
1196 }
Jeff Browne57e8952010-07-23 21:28:06 -07001197
Jeff Brownb51719b2010-07-29 18:18:33 -07001198 mLocked.orientedRanges.orientation.min = - M_PI_2;
1199 mLocked.orientedRanges.orientation.max = M_PI_2;
1200 mLocked.orientedRanges.orientation.flat = 0;
1201 mLocked.orientedRanges.orientation.fuzz = mLocked.orientationScale;
1202
1203 // Configure surface dimensions and orientation.
1204 configureSurfaceLocked();
1205 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001206}
1207
1208void TouchInputMapper::configureAxes() {
1209 mAxes.x.valid = false;
1210 mAxes.y.valid = false;
1211 mAxes.pressure.valid = false;
1212 mAxes.size.valid = false;
1213 mAxes.touchMajor.valid = false;
1214 mAxes.touchMinor.valid = false;
1215 mAxes.toolMajor.valid = false;
1216 mAxes.toolMinor.valid = false;
1217 mAxes.orientation.valid = false;
1218}
1219
Jeff Brownb51719b2010-07-29 18:18:33 -07001220bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001221 // Update orientation and dimensions if needed.
1222 int32_t orientation;
1223 int32_t width, height;
1224 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001225 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001226 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1227 return false;
1228 }
1229 } else {
1230 orientation = InputReaderPolicyInterface::ROTATION_0;
1231 width = mAxes.x.getRange();
1232 height = mAxes.y.getRange();
1233 }
1234
Jeff Brownb51719b2010-07-29 18:18:33 -07001235 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001236 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001237 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001238 }
1239
Jeff Brownb51719b2010-07-29 18:18:33 -07001240 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001241 if (sizeChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001242 mLocked.surfaceWidth = width;
1243 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001244
1245 // Compute size-dependent translation and scaling factors and place virtual keys.
1246 if (mAxes.x.valid && mAxes.y.valid) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001247 mLocked.xOrigin = mAxes.x.minValue;
1248 mLocked.yOrigin = mAxes.y.minValue;
Jeff Browne57e8952010-07-23 21:28:06 -07001249
1250 LOGI("Device configured: id=0x%x, name=%s (display size was changed)",
1251 getDeviceId(), getDeviceName().string());
1252
Jeff Brownb51719b2010-07-29 18:18:33 -07001253 mLocked.xScale = float(width) / mAxes.x.getRange();
1254 mLocked.yScale = float(height) / mAxes.y.getRange();
1255 mLocked.xPrecision = 1.0f / mLocked.xScale;
1256 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001257
Jeff Brownb51719b2010-07-29 18:18:33 -07001258 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001259 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001260 mLocked.xOrigin = 0;
1261 mLocked.yOrigin = 0;
1262 mLocked.xScale = 1.0f;
1263 mLocked.yScale = 1.0f;
1264 mLocked.xPrecision = 1.0f;
1265 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001266 }
1267
1268 // Configure touch and tool area ranges.
1269 float diagonal = sqrt(float(width * width + height * height));
Jeff Brownb51719b2010-07-29 18:18:33 -07001270 float diagonalFuzz = sqrt(mLocked.xScale * mLocked.xScale
1271 + mLocked.yScale * mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001272
Jeff Brownb51719b2010-07-29 18:18:33 -07001273 InputDeviceInfo::MotionRange area;
1274 area.min = 0.0f;
1275 area.max = diagonal;
1276 area.flat = 0.0f;
1277 area.fuzz = diagonalFuzz;
Jeff Browne57e8952010-07-23 21:28:06 -07001278
Jeff Brownb51719b2010-07-29 18:18:33 -07001279 mLocked.orientedRanges.touchMajor = area;
1280 mLocked.orientedRanges.touchMinor = area;
1281
1282 mLocked.orientedRanges.toolMajor = area;
1283 mLocked.orientedRanges.toolMinor = area;
Jeff Browne57e8952010-07-23 21:28:06 -07001284 }
1285
1286 if (orientationChanged || sizeChanged) {
1287 // Compute oriented surface dimensions, precision, and scales.
1288 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001289 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001290 case InputReaderPolicyInterface::ROTATION_90:
1291 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001292 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1293 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1294 mLocked.orientedXPrecision = mLocked.yPrecision;
1295 mLocked.orientedYPrecision = mLocked.xPrecision;
1296 orientedXScale = mLocked.yScale;
1297 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001298 break;
1299 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001300 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1301 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1302 mLocked.orientedXPrecision = mLocked.xPrecision;
1303 mLocked.orientedYPrecision = mLocked.yPrecision;
1304 orientedXScale = mLocked.xScale;
1305 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001306 break;
1307 }
1308
1309 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001310 mLocked.orientedRanges.x.min = 0;
1311 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1312 mLocked.orientedRanges.x.flat = 0;
1313 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001314
Jeff Brownb51719b2010-07-29 18:18:33 -07001315 mLocked.orientedRanges.y.min = 0;
1316 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1317 mLocked.orientedRanges.y.flat = 0;
1318 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001319 }
1320
1321 return true;
1322}
1323
Jeff Brownb51719b2010-07-29 18:18:33 -07001324void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001325 assert(mAxes.x.valid && mAxes.y.valid);
1326
Jeff Brownb51719b2010-07-29 18:18:33 -07001327 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001328 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
1329 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1330
Jeff Brownb51719b2010-07-29 18:18:33 -07001331 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001332
Jeff Brownb51719b2010-07-29 18:18:33 -07001333 if (virtualKeyDefinitions.size() == 0) {
1334 return;
1335 }
Jeff Browne57e8952010-07-23 21:28:06 -07001336
Jeff Brownb51719b2010-07-29 18:18:33 -07001337 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1338
1339 int32_t touchScreenLeft = mAxes.x.minValue;
1340 int32_t touchScreenTop = mAxes.y.minValue;
1341 int32_t touchScreenWidth = mAxes.x.getRange();
1342 int32_t touchScreenHeight = mAxes.y.getRange();
1343
1344 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
1345 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
1346 virtualKeyDefinitions[i];
1347
1348 mLocked.virtualKeys.add();
1349 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1350
1351 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1352 int32_t keyCode;
1353 uint32_t flags;
1354 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1355 & keyCode, & flags)) {
1356 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1357 mLocked.virtualKeys.pop(); // drop the key
1358 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001359 }
1360
Jeff Brownb51719b2010-07-29 18:18:33 -07001361 virtualKey.keyCode = keyCode;
1362 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001363
Jeff Brownb51719b2010-07-29 18:18:33 -07001364 // convert the key definition's display coordinates into touch coordinates for a hit box
1365 int32_t halfWidth = virtualKeyDefinition.width / 2;
1366 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001367
Jeff Brownb51719b2010-07-29 18:18:33 -07001368 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1369 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1370 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1371 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1372 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1373 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1374 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1375 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001376
Jeff Brownb51719b2010-07-29 18:18:33 -07001377 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1378 virtualKey.scanCode, virtualKey.keyCode,
1379 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1380 }
Jeff Browne57e8952010-07-23 21:28:06 -07001381}
1382
1383void TouchInputMapper::reset() {
1384 // Synthesize touch up event if touch is currently down.
1385 // This will also take care of finishing virtual key processing if needed.
1386 if (mLastTouch.pointerCount != 0) {
1387 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1388 mCurrentTouch.clear();
1389 syncTouch(when, true);
1390 }
1391
Jeff Brownb51719b2010-07-29 18:18:33 -07001392 { // acquire lock
1393 AutoMutex _l(mLock);
1394 initializeLocked();
1395 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001396
Jeff Brownb51719b2010-07-29 18:18:33 -07001397 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001398}
1399
1400void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001401 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07001402
1403 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001404 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1405
1406 if (! applyStandardPolicyActions(when, policyActions)) {
1407 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07001408 return; // event dropped
1409 }
1410
Jeff Brownb51719b2010-07-29 18:18:33 -07001411 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07001412
Jeff Browne57e8952010-07-23 21:28:06 -07001413 if (mParameters.useBadTouchFilter) {
1414 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07001415 havePointerIds = false;
1416 }
1417 }
1418
Jeff Browne57e8952010-07-23 21:28:06 -07001419 if (mParameters.useJumpyTouchFilter) {
1420 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07001421 havePointerIds = false;
1422 }
1423 }
1424
1425 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07001426 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07001427 }
1428
Jeff Browne57e8952010-07-23 21:28:06 -07001429 TouchData temp;
1430 TouchData* savedTouch;
1431 if (mParameters.useAveragingTouchFilter) {
1432 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07001433 savedTouch = & temp;
1434
Jeff Browne57e8952010-07-23 21:28:06 -07001435 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07001436 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07001437 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07001438 }
1439
Jeff Brownb51719b2010-07-29 18:18:33 -07001440 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07001441
Jeff Browne57e8952010-07-23 21:28:06 -07001442 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
1443 if (touchResult == DISPATCH_TOUCH) {
1444 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07001445 }
1446
Jeff Brownb51719b2010-07-29 18:18:33 -07001447 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07001448
Jeff Browne57e8952010-07-23 21:28:06 -07001449 if (touchResult == DROP_STROKE) {
1450 mLastTouch.clear();
1451 } else {
1452 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07001453 }
Jeff Browne839a582010-04-22 18:58:52 -07001454}
1455
Jeff Browne57e8952010-07-23 21:28:06 -07001456TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
1457 nsecs_t when, uint32_t policyFlags) {
1458 int32_t keyEventAction, keyEventFlags;
1459 int32_t keyCode, scanCode, downTime;
1460 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07001461
Jeff Brownb51719b2010-07-29 18:18:33 -07001462 { // acquire lock
1463 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001464
Jeff Brownb51719b2010-07-29 18:18:33 -07001465 // Update surface size and orientation, including virtual key positions.
1466 if (! configureSurfaceLocked()) {
1467 return DROP_STROKE;
1468 }
1469
1470 // Check for virtual key press.
1471 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07001472 if (mCurrentTouch.pointerCount == 0) {
1473 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07001474 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07001475#if DEBUG_VIRTUAL_KEYS
1476 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1477 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1478#endif
1479 keyEventAction = AKEY_EVENT_ACTION_UP;
1480 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1481 touchResult = SKIP_TOUCH;
1482 goto DispatchVirtualKey;
1483 }
1484
1485 if (mCurrentTouch.pointerCount == 1) {
1486 int32_t x = mCurrentTouch.pointers[0].x;
1487 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07001488 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
1489 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07001490 // Pointer is still within the space of the virtual key.
1491 return SKIP_TOUCH;
1492 }
1493 }
1494
1495 // Pointer left virtual key area or another pointer also went down.
1496 // Send key cancellation and drop the stroke so subsequent motions will be
1497 // considered fresh downs. This is useful when the user swipes away from the
1498 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07001499 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07001500#if DEBUG_VIRTUAL_KEYS
1501 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1502 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1503#endif
1504 keyEventAction = AKEY_EVENT_ACTION_UP;
1505 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1506 | AKEY_EVENT_FLAG_CANCELED;
1507 touchResult = DROP_STROKE;
1508 goto DispatchVirtualKey;
1509 } else {
1510 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
1511 // Pointer just went down. Handle off-screen touches, if needed.
1512 int32_t x = mCurrentTouch.pointers[0].x;
1513 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07001514 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07001515 // If exactly one pointer went down, check for virtual key hit.
1516 // Otherwise we will drop the entire stroke.
1517 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001518 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07001519 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001520 mLocked.currentVirtualKey.down = true;
1521 mLocked.currentVirtualKey.downTime = when;
1522 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
1523 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07001524#if DEBUG_VIRTUAL_KEYS
1525 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1526 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1527#endif
1528 keyEventAction = AKEY_EVENT_ACTION_DOWN;
1529 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
1530 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1531 touchResult = SKIP_TOUCH;
1532 goto DispatchVirtualKey;
1533 }
1534 }
1535 return DROP_STROKE;
1536 }
1537 }
1538 return DISPATCH_TOUCH;
1539 }
1540
1541 DispatchVirtualKey:
1542 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07001543 keyCode = mLocked.currentVirtualKey.keyCode;
1544 scanCode = mLocked.currentVirtualKey.scanCode;
1545 downTime = mLocked.currentVirtualKey.downTime;
1546 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001547
1548 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07001549 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
1550 keyCode, scanCode, downTime);
1551 return touchResult;
1552}
1553
1554void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
1555 int32_t keyEventAction, int32_t keyEventFlags,
1556 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001557 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07001558
Jeff Brown5c1ed842010-07-14 18:48:53 -07001559 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Browne57e8952010-07-23 21:28:06 -07001560 getPolicy()->virtualKeyDownFeedback();
Jeff Brownf16c26d2010-07-02 15:37:36 -07001561 }
Jeff Browne839a582010-04-22 18:58:52 -07001562
Jeff Browne57e8952010-07-23 21:28:06 -07001563 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001564 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07001565
Jeff Browne57e8952010-07-23 21:28:06 -07001566 if (applyStandardPolicyActions(when, policyActions)) {
1567 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07001568 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1569 }
Jeff Browne839a582010-04-22 18:58:52 -07001570}
1571
Jeff Browne57e8952010-07-23 21:28:06 -07001572void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
1573 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1574 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07001575 if (currentPointerCount == 0 && lastPointerCount == 0) {
1576 return; // nothing to do!
1577 }
1578
Jeff Browne57e8952010-07-23 21:28:06 -07001579 BitSet32 currentIdBits = mCurrentTouch.idBits;
1580 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07001581
1582 if (currentIdBits == lastIdBits) {
1583 // No pointer id changes so this is a move event.
1584 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001585 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001586 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001587 currentIdBits, -1, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07001588 } else {
1589 // There may be pointers going up and pointers going down at the same time when pointer
1590 // ids are reported by the device driver.
1591 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1592 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1593 BitSet32 activeIdBits(lastIdBits.value);
1594
1595 while (! upIdBits.isEmpty()) {
1596 uint32_t upId = upIdBits.firstMarkedBit();
1597 upIdBits.clearBit(upId);
1598 BitSet32 oldActiveIdBits = activeIdBits;
1599 activeIdBits.clearBit(upId);
1600
1601 int32_t motionEventAction;
1602 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001603 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07001604 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001605 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07001606 }
1607
Jeff Browne57e8952010-07-23 21:28:06 -07001608 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001609 oldActiveIdBits, upId, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07001610 }
1611
1612 while (! downIdBits.isEmpty()) {
1613 uint32_t downId = downIdBits.firstMarkedBit();
1614 downIdBits.clearBit(downId);
1615 BitSet32 oldActiveIdBits = activeIdBits;
1616 activeIdBits.markBit(downId);
1617
1618 int32_t motionEventAction;
1619 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001620 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07001621 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07001622 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001623 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07001624 }
1625
Jeff Browne57e8952010-07-23 21:28:06 -07001626 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001627 activeIdBits, downId, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07001628 }
1629 }
1630}
1631
Jeff Browne57e8952010-07-23 21:28:06 -07001632void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
1633 TouchData* touch, BitSet32 idBits, uint32_t changedId,
Jeff Browne839a582010-04-22 18:58:52 -07001634 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07001635 uint32_t pointerCount = 0;
1636 int32_t pointerIds[MAX_POINTERS];
1637 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07001638 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001639 float xPrecision, yPrecision;
1640
1641 { // acquire lock
1642 AutoMutex _l(mLock);
1643
1644 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1645 // display coordinates (PointerCoords) and adjust for display orientation.
1646 while (! idBits.isEmpty()) {
1647 uint32_t id = idBits.firstMarkedBit();
1648 idBits.clearBit(id);
1649 uint32_t index = touch->idToIndex[id];
1650
1651 float x = float(touch->pointers[index].x - mLocked.xOrigin) * mLocked.xScale;
1652 float y = float(touch->pointers[index].y - mLocked.yOrigin) * mLocked.yScale;
1653 float pressure = float(touch->pointers[index].pressure - mLocked.pressureOrigin)
1654 * mLocked.pressureScale;
1655 float size = float(touch->pointers[index].size - mLocked.sizeOrigin)
1656 * mLocked.sizeScale;
1657
1658 float orientation = float(touch->pointers[index].orientation)
1659 * mLocked.orientationScale;
1660
1661 float touchMajor, touchMinor, toolMajor, toolMinor;
1662 if (abs(orientation) <= M_PI_4) {
1663 // Nominally vertical orientation: scale major axis by Y, and scale minor axis by X.
1664 touchMajor = float(touch->pointers[index].touchMajor) * mLocked.yScale;
1665 touchMinor = float(touch->pointers[index].touchMinor) * mLocked.xScale;
1666 toolMajor = float(touch->pointers[index].toolMajor) * mLocked.yScale;
1667 toolMinor = float(touch->pointers[index].toolMinor) * mLocked.xScale;
1668 } else {
1669 // Nominally horizontal orientation: scale major axis by X, and scale minor axis by Y.
1670 touchMajor = float(touch->pointers[index].touchMajor) * mLocked.xScale;
1671 touchMinor = float(touch->pointers[index].touchMinor) * mLocked.yScale;
1672 toolMajor = float(touch->pointers[index].toolMajor) * mLocked.xScale;
1673 toolMinor = float(touch->pointers[index].toolMinor) * mLocked.yScale;
1674 }
1675
1676 switch (mLocked.surfaceOrientation) {
1677 case InputReaderPolicyInterface::ROTATION_90: {
1678 float xTemp = x;
1679 x = y;
1680 y = mLocked.surfaceWidth - xTemp;
1681 orientation -= M_PI_2;
1682 if (orientation < - M_PI_2) {
1683 orientation += M_PI;
1684 }
1685 break;
1686 }
1687 case InputReaderPolicyInterface::ROTATION_180: {
1688 x = mLocked.surfaceWidth - x;
1689 y = mLocked.surfaceHeight - y;
1690 orientation = - orientation;
1691 break;
1692 }
1693 case InputReaderPolicyInterface::ROTATION_270: {
1694 float xTemp = x;
1695 x = mLocked.surfaceHeight - y;
1696 y = xTemp;
1697 orientation += M_PI_2;
1698 if (orientation > M_PI_2) {
1699 orientation -= M_PI;
1700 }
1701 break;
1702 }
1703 }
1704
1705 pointerIds[pointerCount] = int32_t(id);
1706
1707 pointerCoords[pointerCount].x = x;
1708 pointerCoords[pointerCount].y = y;
1709 pointerCoords[pointerCount].pressure = pressure;
1710 pointerCoords[pointerCount].size = size;
1711 pointerCoords[pointerCount].touchMajor = touchMajor;
1712 pointerCoords[pointerCount].touchMinor = touchMinor;
1713 pointerCoords[pointerCount].toolMajor = toolMajor;
1714 pointerCoords[pointerCount].toolMinor = toolMinor;
1715 pointerCoords[pointerCount].orientation = orientation;
1716
1717 if (id == changedId) {
1718 motionEventAction |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
1719 }
1720
1721 pointerCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07001722 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001723
1724 // Check edge flags by looking only at the first pointer since the flags are
1725 // global to the event.
1726 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
1727 if (pointerCoords[0].x <= 0) {
1728 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
1729 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
1730 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
1731 }
1732 if (pointerCoords[0].y <= 0) {
1733 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
1734 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
1735 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
1736 }
Jeff Browne839a582010-04-22 18:58:52 -07001737 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001738
1739 xPrecision = mLocked.orientedXPrecision;
1740 yPrecision = mLocked.orientedYPrecision;
1741 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07001742
Jeff Browne57e8952010-07-23 21:28:06 -07001743 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
1744 motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001745 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07001746 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07001747}
1748
Jeff Brownb51719b2010-07-29 18:18:33 -07001749bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Browne57e8952010-07-23 21:28:06 -07001750 if (mAxes.x.valid && mAxes.y.valid) {
1751 return x >= mAxes.x.minValue && x <= mAxes.x.maxValue
1752 && y >= mAxes.y.minValue && y <= mAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07001753 }
Jeff Browne57e8952010-07-23 21:28:06 -07001754 return true;
1755}
1756
Jeff Brownb51719b2010-07-29 18:18:33 -07001757const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
1758 int32_t x, int32_t y) {
1759 size_t numVirtualKeys = mLocked.virtualKeys.size();
1760 for (size_t i = 0; i < numVirtualKeys; i++) {
1761 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07001762
1763#if DEBUG_VIRTUAL_KEYS
1764 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
1765 "left=%d, top=%d, right=%d, bottom=%d",
1766 x, y,
1767 virtualKey.keyCode, virtualKey.scanCode,
1768 virtualKey.hitLeft, virtualKey.hitTop,
1769 virtualKey.hitRight, virtualKey.hitBottom);
1770#endif
1771
1772 if (virtualKey.isHit(x, y)) {
1773 return & virtualKey;
1774 }
1775 }
1776
1777 return NULL;
1778}
1779
1780void TouchInputMapper::calculatePointerIds() {
1781 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1782 uint32_t lastPointerCount = mLastTouch.pointerCount;
1783
1784 if (currentPointerCount == 0) {
1785 // No pointers to assign.
1786 mCurrentTouch.idBits.clear();
1787 } else if (lastPointerCount == 0) {
1788 // All pointers are new.
1789 mCurrentTouch.idBits.clear();
1790 for (uint32_t i = 0; i < currentPointerCount; i++) {
1791 mCurrentTouch.pointers[i].id = i;
1792 mCurrentTouch.idToIndex[i] = i;
1793 mCurrentTouch.idBits.markBit(i);
1794 }
1795 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
1796 // Only one pointer and no change in count so it must have the same id as before.
1797 uint32_t id = mLastTouch.pointers[0].id;
1798 mCurrentTouch.pointers[0].id = id;
1799 mCurrentTouch.idToIndex[id] = 0;
1800 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
1801 } else {
1802 // General case.
1803 // We build a heap of squared euclidean distances between current and last pointers
1804 // associated with the current and last pointer indices. Then, we find the best
1805 // match (by distance) for each current pointer.
1806 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
1807
1808 uint32_t heapSize = 0;
1809 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
1810 currentPointerIndex++) {
1811 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
1812 lastPointerIndex++) {
1813 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
1814 - mLastTouch.pointers[lastPointerIndex].x;
1815 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
1816 - mLastTouch.pointers[lastPointerIndex].y;
1817
1818 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
1819
1820 // Insert new element into the heap (sift up).
1821 heap[heapSize].currentPointerIndex = currentPointerIndex;
1822 heap[heapSize].lastPointerIndex = lastPointerIndex;
1823 heap[heapSize].distance = distance;
1824 heapSize += 1;
1825 }
1826 }
1827
1828 // Heapify
1829 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
1830 startIndex -= 1;
1831 for (uint32_t parentIndex = startIndex; ;) {
1832 uint32_t childIndex = parentIndex * 2 + 1;
1833 if (childIndex >= heapSize) {
1834 break;
1835 }
1836
1837 if (childIndex + 1 < heapSize
1838 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1839 childIndex += 1;
1840 }
1841
1842 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1843 break;
1844 }
1845
1846 swap(heap[parentIndex], heap[childIndex]);
1847 parentIndex = childIndex;
1848 }
1849 }
1850
1851#if DEBUG_POINTER_ASSIGNMENT
1852 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
1853 for (size_t i = 0; i < heapSize; i++) {
1854 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1855 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1856 heap[i].distance);
1857 }
1858#endif
1859
1860 // Pull matches out by increasing order of distance.
1861 // To avoid reassigning pointers that have already been matched, the loop keeps track
1862 // of which last and current pointers have been matched using the matchedXXXBits variables.
1863 // It also tracks the used pointer id bits.
1864 BitSet32 matchedLastBits(0);
1865 BitSet32 matchedCurrentBits(0);
1866 BitSet32 usedIdBits(0);
1867 bool first = true;
1868 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
1869 for (;;) {
1870 if (first) {
1871 // The first time through the loop, we just consume the root element of
1872 // the heap (the one with smallest distance).
1873 first = false;
1874 } else {
1875 // Previous iterations consumed the root element of the heap.
1876 // Pop root element off of the heap (sift down).
1877 heapSize -= 1;
1878 assert(heapSize > 0);
1879
1880 // Sift down.
1881 heap[0] = heap[heapSize];
1882 for (uint32_t parentIndex = 0; ;) {
1883 uint32_t childIndex = parentIndex * 2 + 1;
1884 if (childIndex >= heapSize) {
1885 break;
1886 }
1887
1888 if (childIndex + 1 < heapSize
1889 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1890 childIndex += 1;
1891 }
1892
1893 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1894 break;
1895 }
1896
1897 swap(heap[parentIndex], heap[childIndex]);
1898 parentIndex = childIndex;
1899 }
1900
1901#if DEBUG_POINTER_ASSIGNMENT
1902 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
1903 for (size_t i = 0; i < heapSize; i++) {
1904 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1905 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1906 heap[i].distance);
1907 }
1908#endif
1909 }
1910
1911 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
1912 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
1913
1914 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
1915 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
1916
1917 matchedCurrentBits.markBit(currentPointerIndex);
1918 matchedLastBits.markBit(lastPointerIndex);
1919
1920 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
1921 mCurrentTouch.pointers[currentPointerIndex].id = id;
1922 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1923 usedIdBits.markBit(id);
1924
1925#if DEBUG_POINTER_ASSIGNMENT
1926 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
1927 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
1928#endif
1929 break;
1930 }
1931 }
1932
1933 // Assign fresh ids to new pointers.
1934 if (currentPointerCount > lastPointerCount) {
1935 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
1936 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
1937 uint32_t id = usedIdBits.firstUnmarkedBit();
1938
1939 mCurrentTouch.pointers[currentPointerIndex].id = id;
1940 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1941 usedIdBits.markBit(id);
1942
1943#if DEBUG_POINTER_ASSIGNMENT
1944 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
1945 currentPointerIndex, id);
1946#endif
1947
1948 if (--i == 0) break; // done
1949 matchedCurrentBits.markBit(currentPointerIndex);
1950 }
1951 }
1952
1953 // Fix id bits.
1954 mCurrentTouch.idBits = usedIdBits;
1955 }
1956}
1957
1958/* Special hack for devices that have bad screen data: if one of the
1959 * points has moved more than a screen height from the last position,
1960 * then drop it. */
1961bool TouchInputMapper::applyBadTouchFilter() {
1962 // This hack requires valid axis parameters.
1963 if (! mAxes.y.valid) {
1964 return false;
1965 }
1966
1967 uint32_t pointerCount = mCurrentTouch.pointerCount;
1968
1969 // Nothing to do if there are no points.
1970 if (pointerCount == 0) {
1971 return false;
1972 }
1973
1974 // Don't do anything if a finger is going down or up. We run
1975 // here before assigning pointer IDs, so there isn't a good
1976 // way to do per-finger matching.
1977 if (pointerCount != mLastTouch.pointerCount) {
1978 return false;
1979 }
1980
1981 // We consider a single movement across more than a 7/16 of
1982 // the long size of the screen to be bad. This was a magic value
1983 // determined by looking at the maximum distance it is feasible
1984 // to actually move in one sample.
1985 int32_t maxDeltaY = mAxes.y.getRange() * 7 / 16;
1986
1987 // XXX The original code in InputDevice.java included commented out
1988 // code for testing the X axis. Note that when we drop a point
1989 // we don't actually restore the old X either. Strange.
1990 // The old code also tries to track when bad points were previously
1991 // detected but it turns out that due to the placement of a "break"
1992 // at the end of the loop, we never set mDroppedBadPoint to true
1993 // so it is effectively dead code.
1994 // Need to figure out if the old code is busted or just overcomplicated
1995 // but working as intended.
1996
1997 // Look through all new points and see if any are farther than
1998 // acceptable from all previous points.
1999 for (uint32_t i = pointerCount; i-- > 0; ) {
2000 int32_t y = mCurrentTouch.pointers[i].y;
2001 int32_t closestY = INT_MAX;
2002 int32_t closestDeltaY = 0;
2003
2004#if DEBUG_HACKS
2005 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2006#endif
2007
2008 for (uint32_t j = pointerCount; j-- > 0; ) {
2009 int32_t lastY = mLastTouch.pointers[j].y;
2010 int32_t deltaY = abs(y - lastY);
2011
2012#if DEBUG_HACKS
2013 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2014 j, lastY, deltaY);
2015#endif
2016
2017 if (deltaY < maxDeltaY) {
2018 goto SkipSufficientlyClosePoint;
2019 }
2020 if (deltaY < closestDeltaY) {
2021 closestDeltaY = deltaY;
2022 closestY = lastY;
2023 }
2024 }
2025
2026 // Must not have found a close enough match.
2027#if DEBUG_HACKS
2028 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2029 i, y, closestY, closestDeltaY, maxDeltaY);
2030#endif
2031
2032 mCurrentTouch.pointers[i].y = closestY;
2033 return true; // XXX original code only corrects one point
2034
2035 SkipSufficientlyClosePoint: ;
2036 }
2037
2038 // No change.
2039 return false;
2040}
2041
2042/* Special hack for devices that have bad screen data: drop points where
2043 * the coordinate value for one axis has jumped to the other pointer's location.
2044 */
2045bool TouchInputMapper::applyJumpyTouchFilter() {
2046 // This hack requires valid axis parameters.
2047 if (! mAxes.y.valid) {
2048 return false;
2049 }
2050
2051 uint32_t pointerCount = mCurrentTouch.pointerCount;
2052 if (mLastTouch.pointerCount != pointerCount) {
2053#if DEBUG_HACKS
2054 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2055 mLastTouch.pointerCount, pointerCount);
2056 for (uint32_t i = 0; i < pointerCount; i++) {
2057 LOGD(" Pointer %d (%d, %d)", i,
2058 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2059 }
2060#endif
2061
2062 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2063 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2064 // Just drop the first few events going from 1 to 2 pointers.
2065 // They're bad often enough that they're not worth considering.
2066 mCurrentTouch.pointerCount = 1;
2067 mJumpyTouchFilter.jumpyPointsDropped += 1;
2068
2069#if DEBUG_HACKS
2070 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2071#endif
2072 return true;
2073 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2074 // The event when we go from 2 -> 1 tends to be messed up too
2075 mCurrentTouch.pointerCount = 2;
2076 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2077 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2078 mJumpyTouchFilter.jumpyPointsDropped += 1;
2079
2080#if DEBUG_HACKS
2081 for (int32_t i = 0; i < 2; i++) {
2082 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2083 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2084 }
2085#endif
2086 return true;
2087 }
2088 }
2089 // Reset jumpy points dropped on other transitions or if limit exceeded.
2090 mJumpyTouchFilter.jumpyPointsDropped = 0;
2091
2092#if DEBUG_HACKS
2093 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2094#endif
2095 return false;
2096 }
2097
2098 // We have the same number of pointers as last time.
2099 // A 'jumpy' point is one where the coordinate value for one axis
2100 // has jumped to the other pointer's location. No need to do anything
2101 // else if we only have one pointer.
2102 if (pointerCount < 2) {
2103 return false;
2104 }
2105
2106 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
2107 int jumpyEpsilon = mAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
2108
2109 // We only replace the single worst jumpy point as characterized by pointer distance
2110 // in a single axis.
2111 int32_t badPointerIndex = -1;
2112 int32_t badPointerReplacementIndex = -1;
2113 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2114
2115 for (uint32_t i = pointerCount; i-- > 0; ) {
2116 int32_t x = mCurrentTouch.pointers[i].x;
2117 int32_t y = mCurrentTouch.pointers[i].y;
2118
2119#if DEBUG_HACKS
2120 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2121#endif
2122
2123 // Check if a touch point is too close to another's coordinates
2124 bool dropX = false, dropY = false;
2125 for (uint32_t j = 0; j < pointerCount; j++) {
2126 if (i == j) {
2127 continue;
2128 }
2129
2130 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2131 dropX = true;
2132 break;
2133 }
2134
2135 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2136 dropY = true;
2137 break;
2138 }
2139 }
2140 if (! dropX && ! dropY) {
2141 continue; // not jumpy
2142 }
2143
2144 // Find a replacement candidate by comparing with older points on the
2145 // complementary (non-jumpy) axis.
2146 int32_t distance = INT_MIN; // distance to be corrected
2147 int32_t replacementIndex = -1;
2148
2149 if (dropX) {
2150 // X looks too close. Find an older replacement point with a close Y.
2151 int32_t smallestDeltaY = INT_MAX;
2152 for (uint32_t j = 0; j < pointerCount; j++) {
2153 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2154 if (deltaY < smallestDeltaY) {
2155 smallestDeltaY = deltaY;
2156 replacementIndex = j;
2157 }
2158 }
2159 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2160 } else {
2161 // Y looks too close. Find an older replacement point with a close X.
2162 int32_t smallestDeltaX = INT_MAX;
2163 for (uint32_t j = 0; j < pointerCount; j++) {
2164 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2165 if (deltaX < smallestDeltaX) {
2166 smallestDeltaX = deltaX;
2167 replacementIndex = j;
2168 }
2169 }
2170 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2171 }
2172
2173 // If replacing this pointer would correct a worse error than the previous ones
2174 // considered, then use this replacement instead.
2175 if (distance > badPointerDistance) {
2176 badPointerIndex = i;
2177 badPointerReplacementIndex = replacementIndex;
2178 badPointerDistance = distance;
2179 }
2180 }
2181
2182 // Correct the jumpy pointer if one was found.
2183 if (badPointerIndex >= 0) {
2184#if DEBUG_HACKS
2185 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2186 badPointerIndex,
2187 mLastTouch.pointers[badPointerReplacementIndex].x,
2188 mLastTouch.pointers[badPointerReplacementIndex].y);
2189#endif
2190
2191 mCurrentTouch.pointers[badPointerIndex].x =
2192 mLastTouch.pointers[badPointerReplacementIndex].x;
2193 mCurrentTouch.pointers[badPointerIndex].y =
2194 mLastTouch.pointers[badPointerReplacementIndex].y;
2195 mJumpyTouchFilter.jumpyPointsDropped += 1;
2196 return true;
2197 }
2198 }
2199
2200 mJumpyTouchFilter.jumpyPointsDropped = 0;
2201 return false;
2202}
2203
2204/* Special hack for devices that have bad screen data: aggregate and
2205 * compute averages of the coordinate data, to reduce the amount of
2206 * jitter seen by applications. */
2207void TouchInputMapper::applyAveragingTouchFilter() {
2208 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2209 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2210 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2211 int32_t y = mCurrentTouch.pointers[currentIndex].y;
2212 int32_t pressure = mCurrentTouch.pointers[currentIndex].pressure;
2213
2214 if (mLastTouch.idBits.hasBit(id)) {
2215 // Pointer was down before and is still down now.
2216 // Compute average over history trace.
2217 uint32_t start = mAveragingTouchFilter.historyStart[id];
2218 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2219
2220 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2221 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2222 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2223
2224#if DEBUG_HACKS
2225 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2226 id, distance);
2227#endif
2228
2229 if (distance < AVERAGING_DISTANCE_LIMIT) {
2230 // Increment end index in preparation for recording new historical data.
2231 end += 1;
2232 if (end > AVERAGING_HISTORY_SIZE) {
2233 end = 0;
2234 }
2235
2236 // If the end index has looped back to the start index then we have filled
2237 // the historical trace up to the desired size so we drop the historical
2238 // data at the start of the trace.
2239 if (end == start) {
2240 start += 1;
2241 if (start > AVERAGING_HISTORY_SIZE) {
2242 start = 0;
2243 }
2244 }
2245
2246 // Add the raw data to the historical trace.
2247 mAveragingTouchFilter.historyStart[id] = start;
2248 mAveragingTouchFilter.historyEnd[id] = end;
2249 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2250 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2251 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2252
2253 // Average over all historical positions in the trace by total pressure.
2254 int32_t averagedX = 0;
2255 int32_t averagedY = 0;
2256 int32_t totalPressure = 0;
2257 for (;;) {
2258 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2259 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2260 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2261 .pointers[id].pressure;
2262
2263 averagedX += historicalX * historicalPressure;
2264 averagedY += historicalY * historicalPressure;
2265 totalPressure += historicalPressure;
2266
2267 if (start == end) {
2268 break;
2269 }
2270
2271 start += 1;
2272 if (start > AVERAGING_HISTORY_SIZE) {
2273 start = 0;
2274 }
2275 }
2276
2277 averagedX /= totalPressure;
2278 averagedY /= totalPressure;
2279
2280#if DEBUG_HACKS
2281 LOGD("AveragingTouchFilter: Pointer id %d - "
2282 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2283 averagedX, averagedY);
2284#endif
2285
2286 mCurrentTouch.pointers[currentIndex].x = averagedX;
2287 mCurrentTouch.pointers[currentIndex].y = averagedY;
2288 } else {
2289#if DEBUG_HACKS
2290 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2291#endif
2292 }
2293 } else {
2294#if DEBUG_HACKS
2295 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2296#endif
2297 }
2298
2299 // Reset pointer history.
2300 mAveragingTouchFilter.historyStart[id] = 0;
2301 mAveragingTouchFilter.historyEnd[id] = 0;
2302 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2303 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2304 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
2305 }
2306}
2307
2308int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002309 { // acquire lock
2310 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002311
Jeff Brownb51719b2010-07-29 18:18:33 -07002312 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002313 return AKEY_STATE_VIRTUAL;
2314 }
2315
Jeff Brownb51719b2010-07-29 18:18:33 -07002316 size_t numVirtualKeys = mLocked.virtualKeys.size();
2317 for (size_t i = 0; i < numVirtualKeys; i++) {
2318 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002319 if (virtualKey.keyCode == keyCode) {
2320 return AKEY_STATE_UP;
2321 }
2322 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002323 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002324
2325 return AKEY_STATE_UNKNOWN;
2326}
2327
2328int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002329 { // acquire lock
2330 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002331
Jeff Brownb51719b2010-07-29 18:18:33 -07002332 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002333 return AKEY_STATE_VIRTUAL;
2334 }
2335
Jeff Brownb51719b2010-07-29 18:18:33 -07002336 size_t numVirtualKeys = mLocked.virtualKeys.size();
2337 for (size_t i = 0; i < numVirtualKeys; i++) {
2338 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002339 if (virtualKey.scanCode == scanCode) {
2340 return AKEY_STATE_UP;
2341 }
2342 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002343 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002344
2345 return AKEY_STATE_UNKNOWN;
2346}
2347
2348bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2349 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002350 { // acquire lock
2351 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002352
Jeff Brownb51719b2010-07-29 18:18:33 -07002353 size_t numVirtualKeys = mLocked.virtualKeys.size();
2354 for (size_t i = 0; i < numVirtualKeys; i++) {
2355 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002356
2357 for (size_t i = 0; i < numCodes; i++) {
2358 if (virtualKey.keyCode == keyCodes[i]) {
2359 outFlags[i] = 1;
2360 }
2361 }
2362 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002363 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002364
2365 return true;
2366}
2367
2368
2369// --- SingleTouchInputMapper ---
2370
2371SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2372 TouchInputMapper(device, associatedDisplayId) {
2373 initialize();
2374}
2375
2376SingleTouchInputMapper::~SingleTouchInputMapper() {
2377}
2378
2379void SingleTouchInputMapper::initialize() {
2380 mAccumulator.clear();
2381
2382 mDown = false;
2383 mX = 0;
2384 mY = 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07002385 mPressure = 1; // default to 1 for devices that don't report pressure
2386 mSize = 0; // default to 0 for devices that don't report size
Jeff Browne57e8952010-07-23 21:28:06 -07002387}
2388
2389void SingleTouchInputMapper::reset() {
2390 TouchInputMapper::reset();
2391
Jeff Browne57e8952010-07-23 21:28:06 -07002392 initialize();
2393 }
2394
2395void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
2396 switch (rawEvent->type) {
2397 case EV_KEY:
2398 switch (rawEvent->scanCode) {
2399 case BTN_TOUCH:
2400 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
2401 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brownd64c8552010-08-17 20:38:35 -07002402 // Don't sync immediately. Wait until the next SYN_REPORT since we might
2403 // not have received valid position information yet. This logic assumes that
2404 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Browne57e8952010-07-23 21:28:06 -07002405 break;
2406 }
2407 break;
2408
2409 case EV_ABS:
2410 switch (rawEvent->scanCode) {
2411 case ABS_X:
2412 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
2413 mAccumulator.absX = rawEvent->value;
2414 break;
2415 case ABS_Y:
2416 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
2417 mAccumulator.absY = rawEvent->value;
2418 break;
2419 case ABS_PRESSURE:
2420 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
2421 mAccumulator.absPressure = rawEvent->value;
2422 break;
2423 case ABS_TOOL_WIDTH:
2424 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
2425 mAccumulator.absToolWidth = rawEvent->value;
2426 break;
2427 }
2428 break;
2429
2430 case EV_SYN:
2431 switch (rawEvent->scanCode) {
2432 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07002433 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07002434 break;
2435 }
2436 break;
2437 }
2438}
2439
2440void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Browne57e8952010-07-23 21:28:06 -07002441 uint32_t fields = mAccumulator.fields;
Jeff Brownd64c8552010-08-17 20:38:35 -07002442 if (fields == 0) {
2443 return; // no new state changes, so nothing to do
2444 }
Jeff Browne57e8952010-07-23 21:28:06 -07002445
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;
Jeff Brownd64c8552010-08-17 20:38:35 -07002475 mCurrentTouch.pointers[0].touchMajor = mSize;
2476 mCurrentTouch.pointers[0].touchMinor = mSize;
Jeff Browne57e8952010-07-23 21:28:06 -07002477 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);
Jeff Brownd64c8552010-08-17 20:38:35 -07002485
2486 mAccumulator.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07002487}
2488
2489void SingleTouchInputMapper::configureAxes() {
2490 TouchInputMapper::configureAxes();
2491
2492 // The axes are aliased to take into account the manner in which they are presented
2493 // as part of the TouchData during the sync.
2494 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mAxes.x);
2495 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mAxes.y);
2496 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure);
2497 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size);
2498
Jeff Brownd64c8552010-08-17 20:38:35 -07002499 mAxes.touchMajor = mAxes.size;
2500 mAxes.touchMinor = mAxes.size;
Jeff Browne57e8952010-07-23 21:28:06 -07002501 mAxes.toolMajor = mAxes.size;
2502 mAxes.toolMinor = mAxes.size;
2503}
2504
2505
2506// --- MultiTouchInputMapper ---
2507
2508MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2509 TouchInputMapper(device, associatedDisplayId) {
2510 initialize();
2511}
2512
2513MultiTouchInputMapper::~MultiTouchInputMapper() {
2514}
2515
2516void MultiTouchInputMapper::initialize() {
2517 mAccumulator.clear();
2518}
2519
2520void MultiTouchInputMapper::reset() {
2521 TouchInputMapper::reset();
2522
Jeff Browne57e8952010-07-23 21:28:06 -07002523 initialize();
2524}
2525
2526void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
2527 switch (rawEvent->type) {
2528 case EV_ABS: {
2529 uint32_t pointerIndex = mAccumulator.pointerCount;
2530 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
2531
2532 switch (rawEvent->scanCode) {
2533 case ABS_MT_POSITION_X:
2534 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
2535 pointer->absMTPositionX = rawEvent->value;
2536 break;
2537 case ABS_MT_POSITION_Y:
2538 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
2539 pointer->absMTPositionY = rawEvent->value;
2540 break;
2541 case ABS_MT_TOUCH_MAJOR:
2542 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
2543 pointer->absMTTouchMajor = rawEvent->value;
2544 break;
2545 case ABS_MT_TOUCH_MINOR:
2546 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
2547 pointer->absMTTouchMinor = rawEvent->value;
2548 break;
2549 case ABS_MT_WIDTH_MAJOR:
2550 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
2551 pointer->absMTWidthMajor = rawEvent->value;
2552 break;
2553 case ABS_MT_WIDTH_MINOR:
2554 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
2555 pointer->absMTWidthMinor = rawEvent->value;
2556 break;
2557 case ABS_MT_ORIENTATION:
2558 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
2559 pointer->absMTOrientation = rawEvent->value;
2560 break;
2561 case ABS_MT_TRACKING_ID:
2562 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
2563 pointer->absMTTrackingId = rawEvent->value;
2564 break;
2565 }
2566 break;
2567 }
2568
2569 case EV_SYN:
2570 switch (rawEvent->scanCode) {
2571 case SYN_MT_REPORT: {
2572 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
2573 uint32_t pointerIndex = mAccumulator.pointerCount;
2574
2575 if (mAccumulator.pointers[pointerIndex].fields) {
2576 if (pointerIndex == MAX_POINTERS) {
2577 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
2578 MAX_POINTERS);
2579 } else {
2580 pointerIndex += 1;
2581 mAccumulator.pointerCount = pointerIndex;
2582 }
2583 }
2584
2585 mAccumulator.pointers[pointerIndex].clear();
2586 break;
2587 }
2588
2589 case SYN_REPORT:
Jeff Brownd64c8552010-08-17 20:38:35 -07002590 sync(rawEvent->when);
Jeff Browne57e8952010-07-23 21:28:06 -07002591 break;
2592 }
2593 break;
2594 }
2595}
2596
2597void MultiTouchInputMapper::sync(nsecs_t when) {
2598 static const uint32_t REQUIRED_FIELDS =
2599 Accumulator::FIELD_ABS_MT_POSITION_X
Jeff Brownd64c8552010-08-17 20:38:35 -07002600 | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Browne839a582010-04-22 18:58:52 -07002601
Jeff Browne57e8952010-07-23 21:28:06 -07002602 uint32_t inCount = mAccumulator.pointerCount;
2603 uint32_t outCount = 0;
2604 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07002605
Jeff Browne57e8952010-07-23 21:28:06 -07002606 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07002607
Jeff Browne57e8952010-07-23 21:28:06 -07002608 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brownd64c8552010-08-17 20:38:35 -07002609 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
2610 uint32_t fields = inPointer.fields;
Jeff Browne839a582010-04-22 18:58:52 -07002611
Jeff Browne57e8952010-07-23 21:28:06 -07002612 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brownd64c8552010-08-17 20:38:35 -07002613 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
2614 // Drop this finger.
Jeff Browne839a582010-04-22 18:58:52 -07002615 continue;
2616 }
2617
Jeff Brownd64c8552010-08-17 20:38:35 -07002618 PointerData& outPointer = mCurrentTouch.pointers[outCount];
2619 outPointer.x = inPointer.absMTPositionX;
2620 outPointer.y = inPointer.absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07002621
Jeff Brownd64c8552010-08-17 20:38:35 -07002622 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
2623 int32_t value = inPointer.absMTTouchMajor;
2624 if (value <= 0) {
2625 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
2626 // a pointer up. Drop this finger.
2627 continue;
2628 }
2629 outPointer.touchMajor = inPointer.absMTTouchMajor;
2630 } else {
2631 outPointer.touchMajor = 0;
2632 }
Jeff Browne839a582010-04-22 18:58:52 -07002633
Jeff Brownd64c8552010-08-17 20:38:35 -07002634 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
2635 outPointer.touchMinor = inPointer.absMTTouchMinor;
2636 } else {
2637 outPointer.touchMinor = outPointer.touchMajor;
2638 }
Jeff Browne839a582010-04-22 18:58:52 -07002639
Jeff Brownd64c8552010-08-17 20:38:35 -07002640 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
2641 outPointer.toolMajor = inPointer.absMTWidthMajor;
2642 } else {
2643 outPointer.toolMajor = outPointer.touchMajor;
2644 }
Jeff Browne839a582010-04-22 18:58:52 -07002645
Jeff Brownd64c8552010-08-17 20:38:35 -07002646 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
2647 outPointer.toolMinor = inPointer.absMTWidthMinor;
2648 } else {
2649 outPointer.toolMinor = outPointer.toolMajor;
2650 }
2651
2652 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
2653 outPointer.orientation = inPointer.absMTOrientation;
2654 } else {
2655 outPointer.orientation = 0;
2656 }
2657
2658 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
2659 outPointer.pressure = inPointer.absMTPressure;
2660 } else {
2661 // Derive an approximation of pressure.
2662 // FIXME Traditionally we have just passed a normalized value based on
2663 // ABS_MT_TOUCH_MAJOR as an estimate of pressure but the result is not
2664 // very meaningful, particularly on large displays. We should probably let
2665 // pressure = touch_major / tool_major but it is unclear whether that will
2666 // break applications.
2667 outPointer.pressure = outPointer.touchMajor;
2668 }
2669
2670 // Size is an alias for a normalized tool width.
2671 // FIXME Normalized tool width doesn't actually make much sense since it literally
2672 // means the approaching contact major axis is divided by its full range as
2673 // reported by the driver. On a large display this could produce very small values.
2674 outPointer.size = outPointer.toolMajor;
Jeff Browne839a582010-04-22 18:58:52 -07002675
Jeff Browne57e8952010-07-23 21:28:06 -07002676 if (havePointerIds) {
Jeff Brownd64c8552010-08-17 20:38:35 -07002677 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
2678 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07002679
Jeff Browne57e8952010-07-23 21:28:06 -07002680 if (id > MAX_POINTER_ID) {
2681#if DEBUG_POINTERS
2682 LOGD("Pointers: Ignoring driver provided pointer id %d because "
2683 "it is larger than max supported id %d for optimizations",
2684 id, MAX_POINTER_ID);
2685#endif
2686 havePointerIds = false;
2687 }
2688 else {
Jeff Brownd64c8552010-08-17 20:38:35 -07002689 outPointer.id = id;
Jeff Browne57e8952010-07-23 21:28:06 -07002690 mCurrentTouch.idToIndex[id] = outCount;
2691 mCurrentTouch.idBits.markBit(id);
2692 }
2693 } else {
2694 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07002695 }
2696 }
Jeff Browne839a582010-04-22 18:58:52 -07002697
Jeff Browne57e8952010-07-23 21:28:06 -07002698 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07002699 }
2700
Jeff Browne57e8952010-07-23 21:28:06 -07002701 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07002702
Jeff Browne57e8952010-07-23 21:28:06 -07002703 syncTouch(when, havePointerIds);
Jeff Brownd64c8552010-08-17 20:38:35 -07002704
2705 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -07002706}
2707
Jeff Browne57e8952010-07-23 21:28:06 -07002708void MultiTouchInputMapper::configureAxes() {
2709 TouchInputMapper::configureAxes();
Jeff Browne839a582010-04-22 18:58:52 -07002710
Jeff Browne57e8952010-07-23 21:28:06 -07002711 // The axes are aliased to take into account the manner in which they are presented
2712 // as part of the TouchData during the sync.
2713 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mAxes.x);
2714 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mAxes.y);
2715 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mAxes.touchMajor);
2716 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mAxes.touchMinor);
2717 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor);
2718 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor);
2719 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation);
Jeff Brownd64c8552010-08-17 20:38:35 -07002720 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mAxes.pressure);
Jeff Brown54bc2812010-06-15 01:31:58 -07002721
Jeff Browne57e8952010-07-23 21:28:06 -07002722 if (! mAxes.touchMinor.valid) {
2723 mAxes.touchMinor = mAxes.touchMajor;
Jeff Brown54bc2812010-06-15 01:31:58 -07002724 }
2725
Jeff Browne57e8952010-07-23 21:28:06 -07002726 if (! mAxes.toolMinor.valid) {
2727 mAxes.toolMinor = mAxes.toolMajor;
2728 }
Jeff Brown54bc2812010-06-15 01:31:58 -07002729
Jeff Brownd64c8552010-08-17 20:38:35 -07002730 if (! mAxes.pressure.valid) {
2731 mAxes.pressure = mAxes.touchMajor;
2732 }
2733
Jeff Browne57e8952010-07-23 21:28:06 -07002734 mAxes.size = mAxes.toolMajor;
Jeff Brown54bc2812010-06-15 01:31:58 -07002735}
2736
Jeff Browne839a582010-04-22 18:58:52 -07002737
2738} // namespace android