blob: 661870212ffd228d23d3c75f16a5e6cb772b1a45 [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 Brownb51719b2010-07-29 18:18:33 -0700948 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -0700949 }
950
Jeff Browne57e8952010-07-23 21:28:06 -0700951 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -0700952}
Jeff Browne839a582010-04-22 18:58:52 -0700953
Jeff Browne57e8952010-07-23 21:28:06 -0700954void TrackballInputMapper::process(const RawEvent* rawEvent) {
955 switch (rawEvent->type) {
956 case EV_KEY:
957 switch (rawEvent->scanCode) {
958 case BTN_MOUSE:
959 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
960 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Browne839a582010-04-22 18:58:52 -0700961
Jeff Browne57e8952010-07-23 21:28:06 -0700962 sync(rawEvent->when);
963 mAccumulator.clear();
964 break;
Jeff Browne839a582010-04-22 18:58:52 -0700965 }
Jeff Browne57e8952010-07-23 21:28:06 -0700966 break;
Jeff Browne839a582010-04-22 18:58:52 -0700967
Jeff Browne57e8952010-07-23 21:28:06 -0700968 case EV_REL:
969 switch (rawEvent->scanCode) {
970 case REL_X:
971 mAccumulator.fields |= Accumulator::FIELD_REL_X;
972 mAccumulator.relX = rawEvent->value;
973 break;
974 case REL_Y:
975 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
976 mAccumulator.relY = rawEvent->value;
977 break;
Jeff Browne839a582010-04-22 18:58:52 -0700978 }
Jeff Browne57e8952010-07-23 21:28:06 -0700979 break;
Jeff Browne839a582010-04-22 18:58:52 -0700980
Jeff Browne57e8952010-07-23 21:28:06 -0700981 case EV_SYN:
982 switch (rawEvent->scanCode) {
983 case SYN_REPORT:
984 if (mAccumulator.isDirty()) {
985 sync(rawEvent->when);
986 mAccumulator.clear();
Jeff Browne839a582010-04-22 18:58:52 -0700987 }
Jeff Browne57e8952010-07-23 21:28:06 -0700988 break;
Jeff Browne839a582010-04-22 18:58:52 -0700989 }
Jeff Browne57e8952010-07-23 21:28:06 -0700990 break;
Jeff Browne839a582010-04-22 18:58:52 -0700991 }
Jeff Browne839a582010-04-22 18:58:52 -0700992}
993
Jeff Browne57e8952010-07-23 21:28:06 -0700994void TrackballInputMapper::sync(nsecs_t when) {
Jeff Brownb51719b2010-07-29 18:18:33 -0700995 int motionEventAction;
996 PointerCoords pointerCoords;
997 nsecs_t downTime;
998 { // acquire lock
999 AutoMutex _l(mLock);
Jeff Browne839a582010-04-22 18:58:52 -07001000
Jeff Brownb51719b2010-07-29 18:18:33 -07001001 uint32_t fields = mAccumulator.fields;
1002 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1003
1004 if (downChanged) {
1005 if (mAccumulator.btnMouse) {
1006 mLocked.down = true;
1007 mLocked.downTime = when;
1008 } else {
1009 mLocked.down = false;
1010 }
Jeff 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);
1064}
1065
1066void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
1067 PointerCoords* pointerCoords, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001068 uint32_t policyFlags = 0;
1069 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1070
1071 if (! applyStandardPolicyActions(when, policyActions)) {
1072 return; // event dropped
1073 }
1074
Jeff Browne57e8952010-07-23 21:28:06 -07001075 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownb51719b2010-07-29 18:18:33 -07001076 int32_t pointerId = 0;
1077
Jeff Browne57e8952010-07-23 21:28:06 -07001078 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
1079 motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb51719b2010-07-29 18:18:33 -07001080 1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browne57e8952010-07-23 21:28:06 -07001081}
1082
1083
1084// --- TouchInputMapper ---
1085
1086TouchInputMapper::TouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
Jeff Brownb51719b2010-07-29 18:18:33 -07001087 InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
1088 mLocked.surfaceOrientation = -1;
1089 mLocked.surfaceWidth = -1;
1090 mLocked.surfaceHeight = -1;
1091
1092 initializeLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001093}
1094
1095TouchInputMapper::~TouchInputMapper() {
1096}
1097
1098uint32_t TouchInputMapper::getSources() {
1099 return mAssociatedDisplayId >= 0 ? AINPUT_SOURCE_TOUCHSCREEN : AINPUT_SOURCE_TOUCHPAD;
1100}
1101
1102void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1103 InputMapper::populateDeviceInfo(info);
1104
Jeff Brownb51719b2010-07-29 18:18:33 -07001105 { // acquire lock
1106 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001107
Jeff Brownb51719b2010-07-29 18:18:33 -07001108 // Ensure surface information is up to date so that orientation changes are
1109 // noticed immediately.
1110 configureSurfaceLocked();
1111
1112 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1113 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
1114 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, mLocked.orientedRanges.pressure);
1115 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE, mLocked.orientedRanges.size);
1116 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR, mLocked.orientedRanges.touchMajor);
1117 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR, mLocked.orientedRanges.touchMinor);
1118 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR, mLocked.orientedRanges.toolMajor);
1119 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR, mLocked.orientedRanges.toolMinor);
1120 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION, mLocked.orientedRanges.orientation);
1121 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001122}
1123
Jeff Brownb51719b2010-07-29 18:18:33 -07001124void TouchInputMapper::initializeLocked() {
1125 mCurrentTouch.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001126 mLastTouch.clear();
1127 mDownTime = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001128
1129 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1130 mAveragingTouchFilter.historyStart[i] = 0;
1131 mAveragingTouchFilter.historyEnd[i] = 0;
1132 }
1133
1134 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001135
1136 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07001137}
1138
1139void TouchInputMapper::configure() {
1140 InputMapper::configure();
1141
1142 // Configure basic parameters.
1143 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1144 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1145 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
1146
1147 // Configure absolute axis information.
1148 configureAxes();
1149
Jeff Brownb51719b2010-07-29 18:18:33 -07001150 { // acquire lock
1151 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001152
Jeff Brownb51719b2010-07-29 18:18:33 -07001153 // Configure pressure factors.
1154 if (mAxes.pressure.valid) {
1155 mLocked.pressureOrigin = mAxes.pressure.minValue;
1156 mLocked.pressureScale = 1.0f / mAxes.pressure.getRange();
1157 } else {
1158 mLocked.pressureOrigin = 0;
1159 mLocked.pressureScale = 1.0f;
1160 }
Jeff Browne57e8952010-07-23 21:28:06 -07001161
Jeff Brownb51719b2010-07-29 18:18:33 -07001162 mLocked.orientedRanges.pressure.min = 0.0f;
1163 mLocked.orientedRanges.pressure.max = 1.0f;
1164 mLocked.orientedRanges.pressure.flat = 0.0f;
1165 mLocked.orientedRanges.pressure.fuzz = mLocked.pressureScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001166
Jeff Brownb51719b2010-07-29 18:18:33 -07001167 // Configure size factors.
1168 if (mAxes.size.valid) {
1169 mLocked.sizeOrigin = mAxes.size.minValue;
1170 mLocked.sizeScale = 1.0f / mAxes.size.getRange();
1171 } else {
1172 mLocked.sizeOrigin = 0;
1173 mLocked.sizeScale = 1.0f;
1174 }
Jeff Browne57e8952010-07-23 21:28:06 -07001175
Jeff Brownb51719b2010-07-29 18:18:33 -07001176 mLocked.orientedRanges.size.min = 0.0f;
1177 mLocked.orientedRanges.size.max = 1.0f;
1178 mLocked.orientedRanges.size.flat = 0.0f;
1179 mLocked.orientedRanges.size.fuzz = mLocked.sizeScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001180
Jeff Brownb51719b2010-07-29 18:18:33 -07001181 // Configure orientation factors.
1182 if (mAxes.orientation.valid && mAxes.orientation.maxValue > 0) {
1183 mLocked.orientationScale = float(M_PI_2) / mAxes.orientation.maxValue;
1184 } else {
1185 mLocked.orientationScale = 0.0f;
1186 }
Jeff Browne57e8952010-07-23 21:28:06 -07001187
Jeff Brownb51719b2010-07-29 18:18:33 -07001188 mLocked.orientedRanges.orientation.min = - M_PI_2;
1189 mLocked.orientedRanges.orientation.max = M_PI_2;
1190 mLocked.orientedRanges.orientation.flat = 0;
1191 mLocked.orientedRanges.orientation.fuzz = mLocked.orientationScale;
1192
1193 // Configure surface dimensions and orientation.
1194 configureSurfaceLocked();
1195 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001196}
1197
1198void TouchInputMapper::configureAxes() {
1199 mAxes.x.valid = false;
1200 mAxes.y.valid = false;
1201 mAxes.pressure.valid = false;
1202 mAxes.size.valid = false;
1203 mAxes.touchMajor.valid = false;
1204 mAxes.touchMinor.valid = false;
1205 mAxes.toolMajor.valid = false;
1206 mAxes.toolMinor.valid = false;
1207 mAxes.orientation.valid = false;
1208}
1209
Jeff Brownb51719b2010-07-29 18:18:33 -07001210bool TouchInputMapper::configureSurfaceLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001211 // Update orientation and dimensions if needed.
1212 int32_t orientation;
1213 int32_t width, height;
1214 if (mAssociatedDisplayId >= 0) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001215 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001216 if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, & width, & height, & orientation)) {
1217 return false;
1218 }
1219 } else {
1220 orientation = InputReaderPolicyInterface::ROTATION_0;
1221 width = mAxes.x.getRange();
1222 height = mAxes.y.getRange();
1223 }
1224
Jeff Brownb51719b2010-07-29 18:18:33 -07001225 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001226 if (orientationChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001227 mLocked.surfaceOrientation = orientation;
Jeff Browne57e8952010-07-23 21:28:06 -07001228 }
1229
Jeff Brownb51719b2010-07-29 18:18:33 -07001230 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Browne57e8952010-07-23 21:28:06 -07001231 if (sizeChanged) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001232 mLocked.surfaceWidth = width;
1233 mLocked.surfaceHeight = height;
Jeff Browne57e8952010-07-23 21:28:06 -07001234
1235 // Compute size-dependent translation and scaling factors and place virtual keys.
1236 if (mAxes.x.valid && mAxes.y.valid) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001237 mLocked.xOrigin = mAxes.x.minValue;
1238 mLocked.yOrigin = mAxes.y.minValue;
Jeff Browne57e8952010-07-23 21:28:06 -07001239
1240 LOGI("Device configured: id=0x%x, name=%s (display size was changed)",
1241 getDeviceId(), getDeviceName().string());
1242
Jeff Brownb51719b2010-07-29 18:18:33 -07001243 mLocked.xScale = float(width) / mAxes.x.getRange();
1244 mLocked.yScale = float(height) / mAxes.y.getRange();
1245 mLocked.xPrecision = 1.0f / mLocked.xScale;
1246 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001247
Jeff Brownb51719b2010-07-29 18:18:33 -07001248 configureVirtualKeysLocked();
Jeff Browne57e8952010-07-23 21:28:06 -07001249 } else {
Jeff Brownb51719b2010-07-29 18:18:33 -07001250 mLocked.xOrigin = 0;
1251 mLocked.yOrigin = 0;
1252 mLocked.xScale = 1.0f;
1253 mLocked.yScale = 1.0f;
1254 mLocked.xPrecision = 1.0f;
1255 mLocked.yPrecision = 1.0f;
Jeff Browne57e8952010-07-23 21:28:06 -07001256 }
1257
1258 // Configure touch and tool area ranges.
1259 float diagonal = sqrt(float(width * width + height * height));
Jeff Brownb51719b2010-07-29 18:18:33 -07001260 float diagonalFuzz = sqrt(mLocked.xScale * mLocked.xScale
1261 + mLocked.yScale * mLocked.yScale);
Jeff Browne57e8952010-07-23 21:28:06 -07001262
Jeff Brownb51719b2010-07-29 18:18:33 -07001263 InputDeviceInfo::MotionRange area;
1264 area.min = 0.0f;
1265 area.max = diagonal;
1266 area.flat = 0.0f;
1267 area.fuzz = diagonalFuzz;
Jeff Browne57e8952010-07-23 21:28:06 -07001268
Jeff Brownb51719b2010-07-29 18:18:33 -07001269 mLocked.orientedRanges.touchMajor = area;
1270 mLocked.orientedRanges.touchMinor = area;
1271
1272 mLocked.orientedRanges.toolMajor = area;
1273 mLocked.orientedRanges.toolMinor = area;
Jeff Browne57e8952010-07-23 21:28:06 -07001274 }
1275
1276 if (orientationChanged || sizeChanged) {
1277 // Compute oriented surface dimensions, precision, and scales.
1278 float orientedXScale, orientedYScale;
Jeff Brownb51719b2010-07-29 18:18:33 -07001279 switch (mLocked.surfaceOrientation) {
Jeff Browne57e8952010-07-23 21:28:06 -07001280 case InputReaderPolicyInterface::ROTATION_90:
1281 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brownb51719b2010-07-29 18:18:33 -07001282 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1283 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1284 mLocked.orientedXPrecision = mLocked.yPrecision;
1285 mLocked.orientedYPrecision = mLocked.xPrecision;
1286 orientedXScale = mLocked.yScale;
1287 orientedYScale = mLocked.xScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001288 break;
1289 default:
Jeff Brownb51719b2010-07-29 18:18:33 -07001290 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1291 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1292 mLocked.orientedXPrecision = mLocked.xPrecision;
1293 mLocked.orientedYPrecision = mLocked.yPrecision;
1294 orientedXScale = mLocked.xScale;
1295 orientedYScale = mLocked.yScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001296 break;
1297 }
1298
1299 // Configure position ranges.
Jeff Brownb51719b2010-07-29 18:18:33 -07001300 mLocked.orientedRanges.x.min = 0;
1301 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1302 mLocked.orientedRanges.x.flat = 0;
1303 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001304
Jeff Brownb51719b2010-07-29 18:18:33 -07001305 mLocked.orientedRanges.y.min = 0;
1306 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1307 mLocked.orientedRanges.y.flat = 0;
1308 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Browne57e8952010-07-23 21:28:06 -07001309 }
1310
1311 return true;
1312}
1313
Jeff Brownb51719b2010-07-29 18:18:33 -07001314void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Browne57e8952010-07-23 21:28:06 -07001315 assert(mAxes.x.valid && mAxes.y.valid);
1316
Jeff Brownb51719b2010-07-29 18:18:33 -07001317 // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Jeff Browne57e8952010-07-23 21:28:06 -07001318 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
1319 getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
1320
Jeff Brownb51719b2010-07-29 18:18:33 -07001321 mLocked.virtualKeys.clear();
Jeff Browne57e8952010-07-23 21:28:06 -07001322
Jeff Brownb51719b2010-07-29 18:18:33 -07001323 if (virtualKeyDefinitions.size() == 0) {
1324 return;
1325 }
Jeff Browne57e8952010-07-23 21:28:06 -07001326
Jeff Brownb51719b2010-07-29 18:18:33 -07001327 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1328
1329 int32_t touchScreenLeft = mAxes.x.minValue;
1330 int32_t touchScreenTop = mAxes.y.minValue;
1331 int32_t touchScreenWidth = mAxes.x.getRange();
1332 int32_t touchScreenHeight = mAxes.y.getRange();
1333
1334 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
1335 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
1336 virtualKeyDefinitions[i];
1337
1338 mLocked.virtualKeys.add();
1339 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1340
1341 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1342 int32_t keyCode;
1343 uint32_t flags;
1344 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1345 & keyCode, & flags)) {
1346 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1347 mLocked.virtualKeys.pop(); // drop the key
1348 continue;
Jeff Browne57e8952010-07-23 21:28:06 -07001349 }
1350
Jeff Brownb51719b2010-07-29 18:18:33 -07001351 virtualKey.keyCode = keyCode;
1352 virtualKey.flags = flags;
Jeff Browne57e8952010-07-23 21:28:06 -07001353
Jeff Brownb51719b2010-07-29 18:18:33 -07001354 // convert the key definition's display coordinates into touch coordinates for a hit box
1355 int32_t halfWidth = virtualKeyDefinition.width / 2;
1356 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Browne57e8952010-07-23 21:28:06 -07001357
Jeff Brownb51719b2010-07-29 18:18:33 -07001358 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1359 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1360 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1361 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1362 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1363 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1364 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1365 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Browne57e8952010-07-23 21:28:06 -07001366
Jeff Brownb51719b2010-07-29 18:18:33 -07001367 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1368 virtualKey.scanCode, virtualKey.keyCode,
1369 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1370 }
Jeff Browne57e8952010-07-23 21:28:06 -07001371}
1372
1373void TouchInputMapper::reset() {
1374 // Synthesize touch up event if touch is currently down.
1375 // This will also take care of finishing virtual key processing if needed.
1376 if (mLastTouch.pointerCount != 0) {
1377 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
1378 mCurrentTouch.clear();
1379 syncTouch(when, true);
1380 }
1381
Jeff Brownb51719b2010-07-29 18:18:33 -07001382 { // acquire lock
1383 AutoMutex _l(mLock);
1384 initializeLocked();
1385 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001386
Jeff Brownb51719b2010-07-29 18:18:33 -07001387 InputMapper::reset();
Jeff Browne57e8952010-07-23 21:28:06 -07001388}
1389
1390void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001391 // Apply generic policy actions.
Jeff Browne839a582010-04-22 18:58:52 -07001392
1393 uint32_t policyFlags = 0;
Jeff Browne57e8952010-07-23 21:28:06 -07001394 int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
1395
1396 if (! applyStandardPolicyActions(when, policyActions)) {
1397 mLastTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07001398 return; // event dropped
1399 }
1400
Jeff Brownb51719b2010-07-29 18:18:33 -07001401 // Preprocess pointer data.
Jeff Browne839a582010-04-22 18:58:52 -07001402
Jeff Browne57e8952010-07-23 21:28:06 -07001403 if (mParameters.useBadTouchFilter) {
1404 if (applyBadTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07001405 havePointerIds = false;
1406 }
1407 }
1408
Jeff Browne57e8952010-07-23 21:28:06 -07001409 if (mParameters.useJumpyTouchFilter) {
1410 if (applyJumpyTouchFilter()) {
Jeff Browne839a582010-04-22 18:58:52 -07001411 havePointerIds = false;
1412 }
1413 }
1414
1415 if (! havePointerIds) {
Jeff Browne57e8952010-07-23 21:28:06 -07001416 calculatePointerIds();
Jeff Browne839a582010-04-22 18:58:52 -07001417 }
1418
Jeff Browne57e8952010-07-23 21:28:06 -07001419 TouchData temp;
1420 TouchData* savedTouch;
1421 if (mParameters.useAveragingTouchFilter) {
1422 temp.copyFrom(mCurrentTouch);
Jeff Browne839a582010-04-22 18:58:52 -07001423 savedTouch = & temp;
1424
Jeff Browne57e8952010-07-23 21:28:06 -07001425 applyAveragingTouchFilter();
Jeff Browne839a582010-04-22 18:58:52 -07001426 } else {
Jeff Browne57e8952010-07-23 21:28:06 -07001427 savedTouch = & mCurrentTouch;
Jeff Browne839a582010-04-22 18:58:52 -07001428 }
1429
Jeff Brownb51719b2010-07-29 18:18:33 -07001430 // Process touches and virtual keys.
Jeff Browne839a582010-04-22 18:58:52 -07001431
Jeff Browne57e8952010-07-23 21:28:06 -07001432 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
1433 if (touchResult == DISPATCH_TOUCH) {
1434 dispatchTouches(when, policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -07001435 }
1436
Jeff Brownb51719b2010-07-29 18:18:33 -07001437 // Copy current touch to last touch in preparation for the next cycle.
Jeff Browne839a582010-04-22 18:58:52 -07001438
Jeff Browne57e8952010-07-23 21:28:06 -07001439 if (touchResult == DROP_STROKE) {
1440 mLastTouch.clear();
1441 } else {
1442 mLastTouch.copyFrom(*savedTouch);
Jeff Browne839a582010-04-22 18:58:52 -07001443 }
Jeff Browne839a582010-04-22 18:58:52 -07001444}
1445
Jeff Browne57e8952010-07-23 21:28:06 -07001446TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
1447 nsecs_t when, uint32_t policyFlags) {
1448 int32_t keyEventAction, keyEventFlags;
1449 int32_t keyCode, scanCode, downTime;
1450 TouchResult touchResult;
Jeff Brown50de30a2010-06-22 01:27:15 -07001451
Jeff Brownb51719b2010-07-29 18:18:33 -07001452 { // acquire lock
1453 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07001454
Jeff Brownb51719b2010-07-29 18:18:33 -07001455 // Update surface size and orientation, including virtual key positions.
1456 if (! configureSurfaceLocked()) {
1457 return DROP_STROKE;
1458 }
1459
1460 // Check for virtual key press.
1461 if (mLocked.currentVirtualKey.down) {
Jeff Browne57e8952010-07-23 21:28:06 -07001462 if (mCurrentTouch.pointerCount == 0) {
1463 // Pointer went up while virtual key was down.
Jeff Brownb51719b2010-07-29 18:18:33 -07001464 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07001465#if DEBUG_VIRTUAL_KEYS
1466 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1467 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1468#endif
1469 keyEventAction = AKEY_EVENT_ACTION_UP;
1470 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1471 touchResult = SKIP_TOUCH;
1472 goto DispatchVirtualKey;
1473 }
1474
1475 if (mCurrentTouch.pointerCount == 1) {
1476 int32_t x = mCurrentTouch.pointers[0].x;
1477 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07001478 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
1479 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07001480 // Pointer is still within the space of the virtual key.
1481 return SKIP_TOUCH;
1482 }
1483 }
1484
1485 // Pointer left virtual key area or another pointer also went down.
1486 // Send key cancellation and drop the stroke so subsequent motions will be
1487 // considered fresh downs. This is useful when the user swipes away from the
1488 // virtual key area into the main display surface.
Jeff Brownb51719b2010-07-29 18:18:33 -07001489 mLocked.currentVirtualKey.down = false;
Jeff Browne57e8952010-07-23 21:28:06 -07001490#if DEBUG_VIRTUAL_KEYS
1491 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1492 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1493#endif
1494 keyEventAction = AKEY_EVENT_ACTION_UP;
1495 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1496 | AKEY_EVENT_FLAG_CANCELED;
1497 touchResult = DROP_STROKE;
1498 goto DispatchVirtualKey;
1499 } else {
1500 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
1501 // Pointer just went down. Handle off-screen touches, if needed.
1502 int32_t x = mCurrentTouch.pointers[0].x;
1503 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brownb51719b2010-07-29 18:18:33 -07001504 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Browne57e8952010-07-23 21:28:06 -07001505 // If exactly one pointer went down, check for virtual key hit.
1506 // Otherwise we will drop the entire stroke.
1507 if (mCurrentTouch.pointerCount == 1) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001508 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Browne57e8952010-07-23 21:28:06 -07001509 if (virtualKey) {
Jeff Brownb51719b2010-07-29 18:18:33 -07001510 mLocked.currentVirtualKey.down = true;
1511 mLocked.currentVirtualKey.downTime = when;
1512 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
1513 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne57e8952010-07-23 21:28:06 -07001514#if DEBUG_VIRTUAL_KEYS
1515 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1516 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
1517#endif
1518 keyEventAction = AKEY_EVENT_ACTION_DOWN;
1519 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
1520 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
1521 touchResult = SKIP_TOUCH;
1522 goto DispatchVirtualKey;
1523 }
1524 }
1525 return DROP_STROKE;
1526 }
1527 }
1528 return DISPATCH_TOUCH;
1529 }
1530
1531 DispatchVirtualKey:
1532 // Collect remaining state needed to dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07001533 keyCode = mLocked.currentVirtualKey.keyCode;
1534 scanCode = mLocked.currentVirtualKey.scanCode;
1535 downTime = mLocked.currentVirtualKey.downTime;
1536 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07001537
1538 // Dispatch virtual key.
Jeff Brownb51719b2010-07-29 18:18:33 -07001539 applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
1540 keyCode, scanCode, downTime);
1541 return touchResult;
1542}
1543
1544void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
1545 int32_t keyEventAction, int32_t keyEventFlags,
1546 int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
Jeff Browne57e8952010-07-23 21:28:06 -07001547 int32_t metaState = mContext->getGlobalMetaState();
Jeff Browne839a582010-04-22 18:58:52 -07001548
Jeff Brown5c1ed842010-07-14 18:48:53 -07001549 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Browne57e8952010-07-23 21:28:06 -07001550 getPolicy()->virtualKeyDownFeedback();
Jeff Brownf16c26d2010-07-02 15:37:36 -07001551 }
Jeff Browne839a582010-04-22 18:58:52 -07001552
Jeff Browne57e8952010-07-23 21:28:06 -07001553 int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
Jeff Brown5c1ed842010-07-14 18:48:53 -07001554 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown50de30a2010-06-22 01:27:15 -07001555
Jeff Browne57e8952010-07-23 21:28:06 -07001556 if (applyStandardPolicyActions(when, policyActions)) {
1557 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown50de30a2010-06-22 01:27:15 -07001558 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1559 }
Jeff Browne839a582010-04-22 18:58:52 -07001560}
1561
Jeff Browne57e8952010-07-23 21:28:06 -07001562void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
1563 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1564 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Browne839a582010-04-22 18:58:52 -07001565 if (currentPointerCount == 0 && lastPointerCount == 0) {
1566 return; // nothing to do!
1567 }
1568
Jeff Browne57e8952010-07-23 21:28:06 -07001569 BitSet32 currentIdBits = mCurrentTouch.idBits;
1570 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Browne839a582010-04-22 18:58:52 -07001571
1572 if (currentIdBits == lastIdBits) {
1573 // No pointer id changes so this is a move event.
1574 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown5c1ed842010-07-14 18:48:53 -07001575 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browne57e8952010-07-23 21:28:06 -07001576 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001577 currentIdBits, -1, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07001578 } else {
1579 // There may be pointers going up and pointers going down at the same time when pointer
1580 // ids are reported by the device driver.
1581 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1582 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1583 BitSet32 activeIdBits(lastIdBits.value);
1584
1585 while (! upIdBits.isEmpty()) {
1586 uint32_t upId = upIdBits.firstMarkedBit();
1587 upIdBits.clearBit(upId);
1588 BitSet32 oldActiveIdBits = activeIdBits;
1589 activeIdBits.clearBit(upId);
1590
1591 int32_t motionEventAction;
1592 if (activeIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001593 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Browne839a582010-04-22 18:58:52 -07001594 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001595 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Browne839a582010-04-22 18:58:52 -07001596 }
1597
Jeff Browne57e8952010-07-23 21:28:06 -07001598 dispatchTouch(when, policyFlags, & mLastTouch,
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001599 oldActiveIdBits, upId, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07001600 }
1601
1602 while (! downIdBits.isEmpty()) {
1603 uint32_t downId = downIdBits.firstMarkedBit();
1604 downIdBits.clearBit(downId);
1605 BitSet32 oldActiveIdBits = activeIdBits;
1606 activeIdBits.markBit(downId);
1607
1608 int32_t motionEventAction;
1609 if (oldActiveIdBits.isEmpty()) {
Jeff Brown5c1ed842010-07-14 18:48:53 -07001610 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Browne57e8952010-07-23 21:28:06 -07001611 mDownTime = when;
Jeff Browne839a582010-04-22 18:58:52 -07001612 } else {
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001613 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -07001614 }
1615
Jeff Browne57e8952010-07-23 21:28:06 -07001616 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown3cf1c9b2010-07-16 15:01:56 -07001617 activeIdBits, downId, motionEventAction);
Jeff Browne839a582010-04-22 18:58:52 -07001618 }
1619 }
1620}
1621
Jeff Browne57e8952010-07-23 21:28:06 -07001622void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
1623 TouchData* touch, BitSet32 idBits, uint32_t changedId,
Jeff Browne839a582010-04-22 18:58:52 -07001624 int32_t motionEventAction) {
Jeff Browne839a582010-04-22 18:58:52 -07001625 uint32_t pointerCount = 0;
1626 int32_t pointerIds[MAX_POINTERS];
1627 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Browne839a582010-04-22 18:58:52 -07001628 int32_t motionEventEdgeFlags = 0;
Jeff Brownb51719b2010-07-29 18:18:33 -07001629 float xPrecision, yPrecision;
1630
1631 { // acquire lock
1632 AutoMutex _l(mLock);
1633
1634 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1635 // display coordinates (PointerCoords) and adjust for display orientation.
1636 while (! idBits.isEmpty()) {
1637 uint32_t id = idBits.firstMarkedBit();
1638 idBits.clearBit(id);
1639 uint32_t index = touch->idToIndex[id];
1640
1641 float x = float(touch->pointers[index].x - mLocked.xOrigin) * mLocked.xScale;
1642 float y = float(touch->pointers[index].y - mLocked.yOrigin) * mLocked.yScale;
1643 float pressure = float(touch->pointers[index].pressure - mLocked.pressureOrigin)
1644 * mLocked.pressureScale;
1645 float size = float(touch->pointers[index].size - mLocked.sizeOrigin)
1646 * mLocked.sizeScale;
1647
1648 float orientation = float(touch->pointers[index].orientation)
1649 * mLocked.orientationScale;
1650
1651 float touchMajor, touchMinor, toolMajor, toolMinor;
1652 if (abs(orientation) <= M_PI_4) {
1653 // Nominally vertical orientation: scale major axis by Y, and scale minor axis by X.
1654 touchMajor = float(touch->pointers[index].touchMajor) * mLocked.yScale;
1655 touchMinor = float(touch->pointers[index].touchMinor) * mLocked.xScale;
1656 toolMajor = float(touch->pointers[index].toolMajor) * mLocked.yScale;
1657 toolMinor = float(touch->pointers[index].toolMinor) * mLocked.xScale;
1658 } else {
1659 // Nominally horizontal orientation: scale major axis by X, and scale minor axis by Y.
1660 touchMajor = float(touch->pointers[index].touchMajor) * mLocked.xScale;
1661 touchMinor = float(touch->pointers[index].touchMinor) * mLocked.yScale;
1662 toolMajor = float(touch->pointers[index].toolMajor) * mLocked.xScale;
1663 toolMinor = float(touch->pointers[index].toolMinor) * mLocked.yScale;
1664 }
1665
1666 switch (mLocked.surfaceOrientation) {
1667 case InputReaderPolicyInterface::ROTATION_90: {
1668 float xTemp = x;
1669 x = y;
1670 y = mLocked.surfaceWidth - xTemp;
1671 orientation -= M_PI_2;
1672 if (orientation < - M_PI_2) {
1673 orientation += M_PI;
1674 }
1675 break;
1676 }
1677 case InputReaderPolicyInterface::ROTATION_180: {
1678 x = mLocked.surfaceWidth - x;
1679 y = mLocked.surfaceHeight - y;
1680 orientation = - orientation;
1681 break;
1682 }
1683 case InputReaderPolicyInterface::ROTATION_270: {
1684 float xTemp = x;
1685 x = mLocked.surfaceHeight - y;
1686 y = xTemp;
1687 orientation += M_PI_2;
1688 if (orientation > M_PI_2) {
1689 orientation -= M_PI;
1690 }
1691 break;
1692 }
1693 }
1694
1695 pointerIds[pointerCount] = int32_t(id);
1696
1697 pointerCoords[pointerCount].x = x;
1698 pointerCoords[pointerCount].y = y;
1699 pointerCoords[pointerCount].pressure = pressure;
1700 pointerCoords[pointerCount].size = size;
1701 pointerCoords[pointerCount].touchMajor = touchMajor;
1702 pointerCoords[pointerCount].touchMinor = touchMinor;
1703 pointerCoords[pointerCount].toolMajor = toolMajor;
1704 pointerCoords[pointerCount].toolMinor = toolMinor;
1705 pointerCoords[pointerCount].orientation = orientation;
1706
1707 if (id == changedId) {
1708 motionEventAction |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
1709 }
1710
1711 pointerCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07001712 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001713
1714 // Check edge flags by looking only at the first pointer since the flags are
1715 // global to the event.
1716 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
1717 if (pointerCoords[0].x <= 0) {
1718 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
1719 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
1720 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
1721 }
1722 if (pointerCoords[0].y <= 0) {
1723 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
1724 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
1725 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
1726 }
Jeff Browne839a582010-04-22 18:58:52 -07001727 }
Jeff Brownb51719b2010-07-29 18:18:33 -07001728
1729 xPrecision = mLocked.orientedXPrecision;
1730 yPrecision = mLocked.orientedYPrecision;
1731 } // release lock
Jeff Browne839a582010-04-22 18:58:52 -07001732
Jeff Browne57e8952010-07-23 21:28:06 -07001733 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
1734 motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Browne839a582010-04-22 18:58:52 -07001735 pointerCount, pointerIds, pointerCoords,
Jeff Brownb51719b2010-07-29 18:18:33 -07001736 xPrecision, yPrecision, mDownTime);
Jeff Browne839a582010-04-22 18:58:52 -07001737}
1738
Jeff Brownb51719b2010-07-29 18:18:33 -07001739bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Browne57e8952010-07-23 21:28:06 -07001740 if (mAxes.x.valid && mAxes.y.valid) {
1741 return x >= mAxes.x.minValue && x <= mAxes.x.maxValue
1742 && y >= mAxes.y.minValue && y <= mAxes.y.maxValue;
Jeff Browne839a582010-04-22 18:58:52 -07001743 }
Jeff Browne57e8952010-07-23 21:28:06 -07001744 return true;
1745}
1746
Jeff Brownb51719b2010-07-29 18:18:33 -07001747const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
1748 int32_t x, int32_t y) {
1749 size_t numVirtualKeys = mLocked.virtualKeys.size();
1750 for (size_t i = 0; i < numVirtualKeys; i++) {
1751 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07001752
1753#if DEBUG_VIRTUAL_KEYS
1754 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
1755 "left=%d, top=%d, right=%d, bottom=%d",
1756 x, y,
1757 virtualKey.keyCode, virtualKey.scanCode,
1758 virtualKey.hitLeft, virtualKey.hitTop,
1759 virtualKey.hitRight, virtualKey.hitBottom);
1760#endif
1761
1762 if (virtualKey.isHit(x, y)) {
1763 return & virtualKey;
1764 }
1765 }
1766
1767 return NULL;
1768}
1769
1770void TouchInputMapper::calculatePointerIds() {
1771 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
1772 uint32_t lastPointerCount = mLastTouch.pointerCount;
1773
1774 if (currentPointerCount == 0) {
1775 // No pointers to assign.
1776 mCurrentTouch.idBits.clear();
1777 } else if (lastPointerCount == 0) {
1778 // All pointers are new.
1779 mCurrentTouch.idBits.clear();
1780 for (uint32_t i = 0; i < currentPointerCount; i++) {
1781 mCurrentTouch.pointers[i].id = i;
1782 mCurrentTouch.idToIndex[i] = i;
1783 mCurrentTouch.idBits.markBit(i);
1784 }
1785 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
1786 // Only one pointer and no change in count so it must have the same id as before.
1787 uint32_t id = mLastTouch.pointers[0].id;
1788 mCurrentTouch.pointers[0].id = id;
1789 mCurrentTouch.idToIndex[id] = 0;
1790 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
1791 } else {
1792 // General case.
1793 // We build a heap of squared euclidean distances between current and last pointers
1794 // associated with the current and last pointer indices. Then, we find the best
1795 // match (by distance) for each current pointer.
1796 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
1797
1798 uint32_t heapSize = 0;
1799 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
1800 currentPointerIndex++) {
1801 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
1802 lastPointerIndex++) {
1803 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
1804 - mLastTouch.pointers[lastPointerIndex].x;
1805 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
1806 - mLastTouch.pointers[lastPointerIndex].y;
1807
1808 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
1809
1810 // Insert new element into the heap (sift up).
1811 heap[heapSize].currentPointerIndex = currentPointerIndex;
1812 heap[heapSize].lastPointerIndex = lastPointerIndex;
1813 heap[heapSize].distance = distance;
1814 heapSize += 1;
1815 }
1816 }
1817
1818 // Heapify
1819 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
1820 startIndex -= 1;
1821 for (uint32_t parentIndex = startIndex; ;) {
1822 uint32_t childIndex = parentIndex * 2 + 1;
1823 if (childIndex >= heapSize) {
1824 break;
1825 }
1826
1827 if (childIndex + 1 < heapSize
1828 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1829 childIndex += 1;
1830 }
1831
1832 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1833 break;
1834 }
1835
1836 swap(heap[parentIndex], heap[childIndex]);
1837 parentIndex = childIndex;
1838 }
1839 }
1840
1841#if DEBUG_POINTER_ASSIGNMENT
1842 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
1843 for (size_t i = 0; i < heapSize; i++) {
1844 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1845 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1846 heap[i].distance);
1847 }
1848#endif
1849
1850 // Pull matches out by increasing order of distance.
1851 // To avoid reassigning pointers that have already been matched, the loop keeps track
1852 // of which last and current pointers have been matched using the matchedXXXBits variables.
1853 // It also tracks the used pointer id bits.
1854 BitSet32 matchedLastBits(0);
1855 BitSet32 matchedCurrentBits(0);
1856 BitSet32 usedIdBits(0);
1857 bool first = true;
1858 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
1859 for (;;) {
1860 if (first) {
1861 // The first time through the loop, we just consume the root element of
1862 // the heap (the one with smallest distance).
1863 first = false;
1864 } else {
1865 // Previous iterations consumed the root element of the heap.
1866 // Pop root element off of the heap (sift down).
1867 heapSize -= 1;
1868 assert(heapSize > 0);
1869
1870 // Sift down.
1871 heap[0] = heap[heapSize];
1872 for (uint32_t parentIndex = 0; ;) {
1873 uint32_t childIndex = parentIndex * 2 + 1;
1874 if (childIndex >= heapSize) {
1875 break;
1876 }
1877
1878 if (childIndex + 1 < heapSize
1879 && heap[childIndex + 1].distance < heap[childIndex].distance) {
1880 childIndex += 1;
1881 }
1882
1883 if (heap[parentIndex].distance <= heap[childIndex].distance) {
1884 break;
1885 }
1886
1887 swap(heap[parentIndex], heap[childIndex]);
1888 parentIndex = childIndex;
1889 }
1890
1891#if DEBUG_POINTER_ASSIGNMENT
1892 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
1893 for (size_t i = 0; i < heapSize; i++) {
1894 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
1895 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
1896 heap[i].distance);
1897 }
1898#endif
1899 }
1900
1901 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
1902 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
1903
1904 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
1905 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
1906
1907 matchedCurrentBits.markBit(currentPointerIndex);
1908 matchedLastBits.markBit(lastPointerIndex);
1909
1910 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
1911 mCurrentTouch.pointers[currentPointerIndex].id = id;
1912 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1913 usedIdBits.markBit(id);
1914
1915#if DEBUG_POINTER_ASSIGNMENT
1916 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
1917 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
1918#endif
1919 break;
1920 }
1921 }
1922
1923 // Assign fresh ids to new pointers.
1924 if (currentPointerCount > lastPointerCount) {
1925 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
1926 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
1927 uint32_t id = usedIdBits.firstUnmarkedBit();
1928
1929 mCurrentTouch.pointers[currentPointerIndex].id = id;
1930 mCurrentTouch.idToIndex[id] = currentPointerIndex;
1931 usedIdBits.markBit(id);
1932
1933#if DEBUG_POINTER_ASSIGNMENT
1934 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
1935 currentPointerIndex, id);
1936#endif
1937
1938 if (--i == 0) break; // done
1939 matchedCurrentBits.markBit(currentPointerIndex);
1940 }
1941 }
1942
1943 // Fix id bits.
1944 mCurrentTouch.idBits = usedIdBits;
1945 }
1946}
1947
1948/* Special hack for devices that have bad screen data: if one of the
1949 * points has moved more than a screen height from the last position,
1950 * then drop it. */
1951bool TouchInputMapper::applyBadTouchFilter() {
1952 // This hack requires valid axis parameters.
1953 if (! mAxes.y.valid) {
1954 return false;
1955 }
1956
1957 uint32_t pointerCount = mCurrentTouch.pointerCount;
1958
1959 // Nothing to do if there are no points.
1960 if (pointerCount == 0) {
1961 return false;
1962 }
1963
1964 // Don't do anything if a finger is going down or up. We run
1965 // here before assigning pointer IDs, so there isn't a good
1966 // way to do per-finger matching.
1967 if (pointerCount != mLastTouch.pointerCount) {
1968 return false;
1969 }
1970
1971 // We consider a single movement across more than a 7/16 of
1972 // the long size of the screen to be bad. This was a magic value
1973 // determined by looking at the maximum distance it is feasible
1974 // to actually move in one sample.
1975 int32_t maxDeltaY = mAxes.y.getRange() * 7 / 16;
1976
1977 // XXX The original code in InputDevice.java included commented out
1978 // code for testing the X axis. Note that when we drop a point
1979 // we don't actually restore the old X either. Strange.
1980 // The old code also tries to track when bad points were previously
1981 // detected but it turns out that due to the placement of a "break"
1982 // at the end of the loop, we never set mDroppedBadPoint to true
1983 // so it is effectively dead code.
1984 // Need to figure out if the old code is busted or just overcomplicated
1985 // but working as intended.
1986
1987 // Look through all new points and see if any are farther than
1988 // acceptable from all previous points.
1989 for (uint32_t i = pointerCount; i-- > 0; ) {
1990 int32_t y = mCurrentTouch.pointers[i].y;
1991 int32_t closestY = INT_MAX;
1992 int32_t closestDeltaY = 0;
1993
1994#if DEBUG_HACKS
1995 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
1996#endif
1997
1998 for (uint32_t j = pointerCount; j-- > 0; ) {
1999 int32_t lastY = mLastTouch.pointers[j].y;
2000 int32_t deltaY = abs(y - lastY);
2001
2002#if DEBUG_HACKS
2003 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2004 j, lastY, deltaY);
2005#endif
2006
2007 if (deltaY < maxDeltaY) {
2008 goto SkipSufficientlyClosePoint;
2009 }
2010 if (deltaY < closestDeltaY) {
2011 closestDeltaY = deltaY;
2012 closestY = lastY;
2013 }
2014 }
2015
2016 // Must not have found a close enough match.
2017#if DEBUG_HACKS
2018 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2019 i, y, closestY, closestDeltaY, maxDeltaY);
2020#endif
2021
2022 mCurrentTouch.pointers[i].y = closestY;
2023 return true; // XXX original code only corrects one point
2024
2025 SkipSufficientlyClosePoint: ;
2026 }
2027
2028 // No change.
2029 return false;
2030}
2031
2032/* Special hack for devices that have bad screen data: drop points where
2033 * the coordinate value for one axis has jumped to the other pointer's location.
2034 */
2035bool TouchInputMapper::applyJumpyTouchFilter() {
2036 // This hack requires valid axis parameters.
2037 if (! mAxes.y.valid) {
2038 return false;
2039 }
2040
2041 uint32_t pointerCount = mCurrentTouch.pointerCount;
2042 if (mLastTouch.pointerCount != pointerCount) {
2043#if DEBUG_HACKS
2044 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2045 mLastTouch.pointerCount, pointerCount);
2046 for (uint32_t i = 0; i < pointerCount; i++) {
2047 LOGD(" Pointer %d (%d, %d)", i,
2048 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2049 }
2050#endif
2051
2052 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2053 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2054 // Just drop the first few events going from 1 to 2 pointers.
2055 // They're bad often enough that they're not worth considering.
2056 mCurrentTouch.pointerCount = 1;
2057 mJumpyTouchFilter.jumpyPointsDropped += 1;
2058
2059#if DEBUG_HACKS
2060 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2061#endif
2062 return true;
2063 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2064 // The event when we go from 2 -> 1 tends to be messed up too
2065 mCurrentTouch.pointerCount = 2;
2066 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2067 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2068 mJumpyTouchFilter.jumpyPointsDropped += 1;
2069
2070#if DEBUG_HACKS
2071 for (int32_t i = 0; i < 2; i++) {
2072 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
2073 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2074 }
2075#endif
2076 return true;
2077 }
2078 }
2079 // Reset jumpy points dropped on other transitions or if limit exceeded.
2080 mJumpyTouchFilter.jumpyPointsDropped = 0;
2081
2082#if DEBUG_HACKS
2083 LOGD("JumpyTouchFilter: Transition - drop limit reset");
2084#endif
2085 return false;
2086 }
2087
2088 // We have the same number of pointers as last time.
2089 // A 'jumpy' point is one where the coordinate value for one axis
2090 // has jumped to the other pointer's location. No need to do anything
2091 // else if we only have one pointer.
2092 if (pointerCount < 2) {
2093 return false;
2094 }
2095
2096 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
2097 int jumpyEpsilon = mAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
2098
2099 // We only replace the single worst jumpy point as characterized by pointer distance
2100 // in a single axis.
2101 int32_t badPointerIndex = -1;
2102 int32_t badPointerReplacementIndex = -1;
2103 int32_t badPointerDistance = INT_MIN; // distance to be corrected
2104
2105 for (uint32_t i = pointerCount; i-- > 0; ) {
2106 int32_t x = mCurrentTouch.pointers[i].x;
2107 int32_t y = mCurrentTouch.pointers[i].y;
2108
2109#if DEBUG_HACKS
2110 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
2111#endif
2112
2113 // Check if a touch point is too close to another's coordinates
2114 bool dropX = false, dropY = false;
2115 for (uint32_t j = 0; j < pointerCount; j++) {
2116 if (i == j) {
2117 continue;
2118 }
2119
2120 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
2121 dropX = true;
2122 break;
2123 }
2124
2125 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
2126 dropY = true;
2127 break;
2128 }
2129 }
2130 if (! dropX && ! dropY) {
2131 continue; // not jumpy
2132 }
2133
2134 // Find a replacement candidate by comparing with older points on the
2135 // complementary (non-jumpy) axis.
2136 int32_t distance = INT_MIN; // distance to be corrected
2137 int32_t replacementIndex = -1;
2138
2139 if (dropX) {
2140 // X looks too close. Find an older replacement point with a close Y.
2141 int32_t smallestDeltaY = INT_MAX;
2142 for (uint32_t j = 0; j < pointerCount; j++) {
2143 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
2144 if (deltaY < smallestDeltaY) {
2145 smallestDeltaY = deltaY;
2146 replacementIndex = j;
2147 }
2148 }
2149 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
2150 } else {
2151 // Y looks too close. Find an older replacement point with a close X.
2152 int32_t smallestDeltaX = INT_MAX;
2153 for (uint32_t j = 0; j < pointerCount; j++) {
2154 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
2155 if (deltaX < smallestDeltaX) {
2156 smallestDeltaX = deltaX;
2157 replacementIndex = j;
2158 }
2159 }
2160 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
2161 }
2162
2163 // If replacing this pointer would correct a worse error than the previous ones
2164 // considered, then use this replacement instead.
2165 if (distance > badPointerDistance) {
2166 badPointerIndex = i;
2167 badPointerReplacementIndex = replacementIndex;
2168 badPointerDistance = distance;
2169 }
2170 }
2171
2172 // Correct the jumpy pointer if one was found.
2173 if (badPointerIndex >= 0) {
2174#if DEBUG_HACKS
2175 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
2176 badPointerIndex,
2177 mLastTouch.pointers[badPointerReplacementIndex].x,
2178 mLastTouch.pointers[badPointerReplacementIndex].y);
2179#endif
2180
2181 mCurrentTouch.pointers[badPointerIndex].x =
2182 mLastTouch.pointers[badPointerReplacementIndex].x;
2183 mCurrentTouch.pointers[badPointerIndex].y =
2184 mLastTouch.pointers[badPointerReplacementIndex].y;
2185 mJumpyTouchFilter.jumpyPointsDropped += 1;
2186 return true;
2187 }
2188 }
2189
2190 mJumpyTouchFilter.jumpyPointsDropped = 0;
2191 return false;
2192}
2193
2194/* Special hack for devices that have bad screen data: aggregate and
2195 * compute averages of the coordinate data, to reduce the amount of
2196 * jitter seen by applications. */
2197void TouchInputMapper::applyAveragingTouchFilter() {
2198 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
2199 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
2200 int32_t x = mCurrentTouch.pointers[currentIndex].x;
2201 int32_t y = mCurrentTouch.pointers[currentIndex].y;
2202 int32_t pressure = mCurrentTouch.pointers[currentIndex].pressure;
2203
2204 if (mLastTouch.idBits.hasBit(id)) {
2205 // Pointer was down before and is still down now.
2206 // Compute average over history trace.
2207 uint32_t start = mAveragingTouchFilter.historyStart[id];
2208 uint32_t end = mAveragingTouchFilter.historyEnd[id];
2209
2210 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
2211 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
2212 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2213
2214#if DEBUG_HACKS
2215 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
2216 id, distance);
2217#endif
2218
2219 if (distance < AVERAGING_DISTANCE_LIMIT) {
2220 // Increment end index in preparation for recording new historical data.
2221 end += 1;
2222 if (end > AVERAGING_HISTORY_SIZE) {
2223 end = 0;
2224 }
2225
2226 // If the end index has looped back to the start index then we have filled
2227 // the historical trace up to the desired size so we drop the historical
2228 // data at the start of the trace.
2229 if (end == start) {
2230 start += 1;
2231 if (start > AVERAGING_HISTORY_SIZE) {
2232 start = 0;
2233 }
2234 }
2235
2236 // Add the raw data to the historical trace.
2237 mAveragingTouchFilter.historyStart[id] = start;
2238 mAveragingTouchFilter.historyEnd[id] = end;
2239 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
2240 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
2241 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
2242
2243 // Average over all historical positions in the trace by total pressure.
2244 int32_t averagedX = 0;
2245 int32_t averagedY = 0;
2246 int32_t totalPressure = 0;
2247 for (;;) {
2248 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
2249 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
2250 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
2251 .pointers[id].pressure;
2252
2253 averagedX += historicalX * historicalPressure;
2254 averagedY += historicalY * historicalPressure;
2255 totalPressure += historicalPressure;
2256
2257 if (start == end) {
2258 break;
2259 }
2260
2261 start += 1;
2262 if (start > AVERAGING_HISTORY_SIZE) {
2263 start = 0;
2264 }
2265 }
2266
2267 averagedX /= totalPressure;
2268 averagedY /= totalPressure;
2269
2270#if DEBUG_HACKS
2271 LOGD("AveragingTouchFilter: Pointer id %d - "
2272 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
2273 averagedX, averagedY);
2274#endif
2275
2276 mCurrentTouch.pointers[currentIndex].x = averagedX;
2277 mCurrentTouch.pointers[currentIndex].y = averagedY;
2278 } else {
2279#if DEBUG_HACKS
2280 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
2281#endif
2282 }
2283 } else {
2284#if DEBUG_HACKS
2285 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
2286#endif
2287 }
2288
2289 // Reset pointer history.
2290 mAveragingTouchFilter.historyStart[id] = 0;
2291 mAveragingTouchFilter.historyEnd[id] = 0;
2292 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
2293 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
2294 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
2295 }
2296}
2297
2298int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002299 { // acquire lock
2300 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002301
Jeff Brownb51719b2010-07-29 18:18:33 -07002302 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002303 return AKEY_STATE_VIRTUAL;
2304 }
2305
Jeff Brownb51719b2010-07-29 18:18:33 -07002306 size_t numVirtualKeys = mLocked.virtualKeys.size();
2307 for (size_t i = 0; i < numVirtualKeys; i++) {
2308 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002309 if (virtualKey.keyCode == keyCode) {
2310 return AKEY_STATE_UP;
2311 }
2312 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002313 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002314
2315 return AKEY_STATE_UNKNOWN;
2316}
2317
2318int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002319 { // acquire lock
2320 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002321
Jeff Brownb51719b2010-07-29 18:18:33 -07002322 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Browne57e8952010-07-23 21:28:06 -07002323 return AKEY_STATE_VIRTUAL;
2324 }
2325
Jeff Brownb51719b2010-07-29 18:18:33 -07002326 size_t numVirtualKeys = mLocked.virtualKeys.size();
2327 for (size_t i = 0; i < numVirtualKeys; i++) {
2328 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002329 if (virtualKey.scanCode == scanCode) {
2330 return AKEY_STATE_UP;
2331 }
2332 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002333 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002334
2335 return AKEY_STATE_UNKNOWN;
2336}
2337
2338bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
2339 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownb51719b2010-07-29 18:18:33 -07002340 { // acquire lock
2341 AutoMutex _l(mLock);
Jeff Browne57e8952010-07-23 21:28:06 -07002342
Jeff Brownb51719b2010-07-29 18:18:33 -07002343 size_t numVirtualKeys = mLocked.virtualKeys.size();
2344 for (size_t i = 0; i < numVirtualKeys; i++) {
2345 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Browne57e8952010-07-23 21:28:06 -07002346
2347 for (size_t i = 0; i < numCodes; i++) {
2348 if (virtualKey.keyCode == keyCodes[i]) {
2349 outFlags[i] = 1;
2350 }
2351 }
2352 }
Jeff Brownb51719b2010-07-29 18:18:33 -07002353 } // release lock
Jeff Browne57e8952010-07-23 21:28:06 -07002354
2355 return true;
2356}
2357
2358
2359// --- SingleTouchInputMapper ---
2360
2361SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2362 TouchInputMapper(device, associatedDisplayId) {
2363 initialize();
2364}
2365
2366SingleTouchInputMapper::~SingleTouchInputMapper() {
2367}
2368
2369void SingleTouchInputMapper::initialize() {
2370 mAccumulator.clear();
2371
2372 mDown = false;
2373 mX = 0;
2374 mY = 0;
2375 mPressure = 0;
2376 mSize = 0;
2377}
2378
2379void SingleTouchInputMapper::reset() {
2380 TouchInputMapper::reset();
2381
Jeff Browne57e8952010-07-23 21:28:06 -07002382 initialize();
2383 }
2384
2385void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
2386 switch (rawEvent->type) {
2387 case EV_KEY:
2388 switch (rawEvent->scanCode) {
2389 case BTN_TOUCH:
2390 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
2391 mAccumulator.btnTouch = rawEvent->value != 0;
2392
2393 sync(rawEvent->when);
2394 mAccumulator.clear();
2395 break;
2396 }
2397 break;
2398
2399 case EV_ABS:
2400 switch (rawEvent->scanCode) {
2401 case ABS_X:
2402 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
2403 mAccumulator.absX = rawEvent->value;
2404 break;
2405 case ABS_Y:
2406 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
2407 mAccumulator.absY = rawEvent->value;
2408 break;
2409 case ABS_PRESSURE:
2410 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
2411 mAccumulator.absPressure = rawEvent->value;
2412 break;
2413 case ABS_TOOL_WIDTH:
2414 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
2415 mAccumulator.absToolWidth = rawEvent->value;
2416 break;
2417 }
2418 break;
2419
2420 case EV_SYN:
2421 switch (rawEvent->scanCode) {
2422 case SYN_REPORT:
2423 if (mAccumulator.isDirty()) {
2424 sync(rawEvent->when);
2425 mAccumulator.clear();
2426 }
2427 break;
2428 }
2429 break;
2430 }
2431}
2432
2433void SingleTouchInputMapper::sync(nsecs_t when) {
2434 /* Update device state */
2435
2436 uint32_t fields = mAccumulator.fields;
2437
2438 if (fields & Accumulator::FIELD_BTN_TOUCH) {
2439 mDown = mAccumulator.btnTouch;
2440 }
2441
2442 if (fields & Accumulator::FIELD_ABS_X) {
2443 mX = mAccumulator.absX;
2444 }
2445
2446 if (fields & Accumulator::FIELD_ABS_Y) {
2447 mY = mAccumulator.absY;
2448 }
2449
2450 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
2451 mPressure = mAccumulator.absPressure;
2452 }
2453
2454 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
2455 mSize = mAccumulator.absToolWidth;
2456 }
2457
2458 mCurrentTouch.clear();
2459
2460 if (mDown) {
2461 mCurrentTouch.pointerCount = 1;
2462 mCurrentTouch.pointers[0].id = 0;
2463 mCurrentTouch.pointers[0].x = mX;
2464 mCurrentTouch.pointers[0].y = mY;
2465 mCurrentTouch.pointers[0].pressure = mPressure;
2466 mCurrentTouch.pointers[0].size = mSize;
2467 mCurrentTouch.pointers[0].touchMajor = mPressure;
2468 mCurrentTouch.pointers[0].touchMinor = mPressure;
2469 mCurrentTouch.pointers[0].toolMajor = mSize;
2470 mCurrentTouch.pointers[0].toolMinor = mSize;
2471 mCurrentTouch.pointers[0].orientation = 0;
2472 mCurrentTouch.idToIndex[0] = 0;
2473 mCurrentTouch.idBits.markBit(0);
2474 }
2475
2476 syncTouch(when, true);
2477}
2478
2479void SingleTouchInputMapper::configureAxes() {
2480 TouchInputMapper::configureAxes();
2481
2482 // The axes are aliased to take into account the manner in which they are presented
2483 // as part of the TouchData during the sync.
2484 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mAxes.x);
2485 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mAxes.y);
2486 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mAxes.pressure);
2487 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mAxes.size);
2488
2489 mAxes.touchMajor = mAxes.pressure;
2490 mAxes.touchMinor = mAxes.pressure;
2491 mAxes.toolMajor = mAxes.size;
2492 mAxes.toolMinor = mAxes.size;
2493}
2494
2495
2496// --- MultiTouchInputMapper ---
2497
2498MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId) :
2499 TouchInputMapper(device, associatedDisplayId) {
2500 initialize();
2501}
2502
2503MultiTouchInputMapper::~MultiTouchInputMapper() {
2504}
2505
2506void MultiTouchInputMapper::initialize() {
2507 mAccumulator.clear();
2508}
2509
2510void MultiTouchInputMapper::reset() {
2511 TouchInputMapper::reset();
2512
Jeff Browne57e8952010-07-23 21:28:06 -07002513 initialize();
2514}
2515
2516void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
2517 switch (rawEvent->type) {
2518 case EV_ABS: {
2519 uint32_t pointerIndex = mAccumulator.pointerCount;
2520 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
2521
2522 switch (rawEvent->scanCode) {
2523 case ABS_MT_POSITION_X:
2524 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
2525 pointer->absMTPositionX = rawEvent->value;
2526 break;
2527 case ABS_MT_POSITION_Y:
2528 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
2529 pointer->absMTPositionY = rawEvent->value;
2530 break;
2531 case ABS_MT_TOUCH_MAJOR:
2532 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
2533 pointer->absMTTouchMajor = rawEvent->value;
2534 break;
2535 case ABS_MT_TOUCH_MINOR:
2536 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
2537 pointer->absMTTouchMinor = rawEvent->value;
2538 break;
2539 case ABS_MT_WIDTH_MAJOR:
2540 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
2541 pointer->absMTWidthMajor = rawEvent->value;
2542 break;
2543 case ABS_MT_WIDTH_MINOR:
2544 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
2545 pointer->absMTWidthMinor = rawEvent->value;
2546 break;
2547 case ABS_MT_ORIENTATION:
2548 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
2549 pointer->absMTOrientation = rawEvent->value;
2550 break;
2551 case ABS_MT_TRACKING_ID:
2552 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
2553 pointer->absMTTrackingId = rawEvent->value;
2554 break;
2555 }
2556 break;
2557 }
2558
2559 case EV_SYN:
2560 switch (rawEvent->scanCode) {
2561 case SYN_MT_REPORT: {
2562 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
2563 uint32_t pointerIndex = mAccumulator.pointerCount;
2564
2565 if (mAccumulator.pointers[pointerIndex].fields) {
2566 if (pointerIndex == MAX_POINTERS) {
2567 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
2568 MAX_POINTERS);
2569 } else {
2570 pointerIndex += 1;
2571 mAccumulator.pointerCount = pointerIndex;
2572 }
2573 }
2574
2575 mAccumulator.pointers[pointerIndex].clear();
2576 break;
2577 }
2578
2579 case SYN_REPORT:
2580 if (mAccumulator.isDirty()) {
2581 sync(rawEvent->when);
2582 mAccumulator.clear();
2583 }
2584 break;
2585 }
2586 break;
2587 }
2588}
2589
2590void MultiTouchInputMapper::sync(nsecs_t when) {
2591 static const uint32_t REQUIRED_FIELDS =
2592 Accumulator::FIELD_ABS_MT_POSITION_X
2593 | Accumulator::FIELD_ABS_MT_POSITION_Y
2594 | Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
2595 | Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
Jeff Browne839a582010-04-22 18:58:52 -07002596
2597 /* Update device state */
2598
Jeff Browne57e8952010-07-23 21:28:06 -07002599 uint32_t inCount = mAccumulator.pointerCount;
2600 uint32_t outCount = 0;
2601 bool havePointerIds = true;
Jeff Browne839a582010-04-22 18:58:52 -07002602
Jeff Browne57e8952010-07-23 21:28:06 -07002603 mCurrentTouch.clear();
Jeff Browne839a582010-04-22 18:58:52 -07002604
Jeff Browne57e8952010-07-23 21:28:06 -07002605 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
2606 uint32_t fields = mAccumulator.pointers[inIndex].fields;
Jeff Browne839a582010-04-22 18:58:52 -07002607
Jeff Browne57e8952010-07-23 21:28:06 -07002608 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
2609#if DEBUG_POINTERS
2610 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
2611 inIndex, fields);
2612 continue;
2613#endif
Jeff Browne839a582010-04-22 18:58:52 -07002614 }
2615
Jeff Browne57e8952010-07-23 21:28:06 -07002616 if (mAccumulator.pointers[inIndex].absMTTouchMajor <= 0) {
2617 // Pointer is not down. Drop it.
Jeff Browne839a582010-04-22 18:58:52 -07002618 continue;
2619 }
2620
Jeff Browne57e8952010-07-23 21:28:06 -07002621 mCurrentTouch.pointers[outCount].x = mAccumulator.pointers[inIndex].absMTPositionX;
2622 mCurrentTouch.pointers[outCount].y = mAccumulator.pointers[inIndex].absMTPositionY;
Jeff Browne839a582010-04-22 18:58:52 -07002623
Jeff Browne57e8952010-07-23 21:28:06 -07002624 mCurrentTouch.pointers[outCount].touchMajor =
2625 mAccumulator.pointers[inIndex].absMTTouchMajor;
2626 mCurrentTouch.pointers[outCount].touchMinor =
2627 (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
2628 ? mAccumulator.pointers[inIndex].absMTTouchMinor
2629 : mAccumulator.pointers[inIndex].absMTTouchMajor;
Jeff Browne839a582010-04-22 18:58:52 -07002630
Jeff Browne57e8952010-07-23 21:28:06 -07002631 mCurrentTouch.pointers[outCount].toolMajor =
2632 mAccumulator.pointers[inIndex].absMTWidthMajor;
2633 mCurrentTouch.pointers[outCount].toolMinor =
2634 (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
2635 ? mAccumulator.pointers[inIndex].absMTWidthMinor
2636 : mAccumulator.pointers[inIndex].absMTWidthMajor;
Jeff Browne839a582010-04-22 18:58:52 -07002637
Jeff Browne57e8952010-07-23 21:28:06 -07002638 mCurrentTouch.pointers[outCount].orientation =
2639 (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
2640 ? mAccumulator.pointers[inIndex].absMTOrientation : 0;
Jeff Browne839a582010-04-22 18:58:52 -07002641
Jeff Browne57e8952010-07-23 21:28:06 -07002642 // Derive an approximation of pressure and size.
2643 // FIXME assignment of pressure may be incorrect, probably better to let
2644 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
2645 // isn't quite right either. Should be using touch for that.
2646 mCurrentTouch.pointers[outCount].pressure = mAccumulator.pointers[inIndex].absMTTouchMajor;
2647 mCurrentTouch.pointers[outCount].size = mAccumulator.pointers[inIndex].absMTWidthMajor;
Jeff Browne839a582010-04-22 18:58:52 -07002648
Jeff Browne57e8952010-07-23 21:28:06 -07002649 if (havePointerIds) {
2650 if (fields & Accumulator::
2651 FIELD_ABS_MT_TRACKING_ID) {
2652 uint32_t id = uint32_t(mAccumulator.pointers[inIndex].absMTTrackingId);
Jeff Browne839a582010-04-22 18:58:52 -07002653
Jeff Browne57e8952010-07-23 21:28:06 -07002654 if (id > MAX_POINTER_ID) {
2655#if DEBUG_POINTERS
2656 LOGD("Pointers: Ignoring driver provided pointer id %d because "
2657 "it is larger than max supported id %d for optimizations",
2658 id, MAX_POINTER_ID);
2659#endif
2660 havePointerIds = false;
2661 }
2662 else {
2663 mCurrentTouch.pointers[outCount].id = id;
2664 mCurrentTouch.idToIndex[id] = outCount;
2665 mCurrentTouch.idBits.markBit(id);
2666 }
2667 } else {
2668 havePointerIds = false;
Jeff Browne839a582010-04-22 18:58:52 -07002669 }
2670 }
Jeff Browne839a582010-04-22 18:58:52 -07002671
Jeff Browne57e8952010-07-23 21:28:06 -07002672 outCount += 1;
Jeff Browne839a582010-04-22 18:58:52 -07002673 }
2674
Jeff Browne57e8952010-07-23 21:28:06 -07002675 mCurrentTouch.pointerCount = outCount;
Jeff Browne839a582010-04-22 18:58:52 -07002676
Jeff Browne57e8952010-07-23 21:28:06 -07002677 syncTouch(when, havePointerIds);
Jeff Browne839a582010-04-22 18:58:52 -07002678}
2679
Jeff Browne57e8952010-07-23 21:28:06 -07002680void MultiTouchInputMapper::configureAxes() {
2681 TouchInputMapper::configureAxes();
Jeff Browne839a582010-04-22 18:58:52 -07002682
Jeff Browne57e8952010-07-23 21:28:06 -07002683 // The axes are aliased to take into account the manner in which they are presented
2684 // as part of the TouchData during the sync.
2685 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mAxes.x);
2686 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mAxes.y);
2687 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mAxes.touchMajor);
2688 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mAxes.touchMinor);
2689 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mAxes.toolMajor);
2690 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mAxes.toolMinor);
2691 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mAxes.orientation);
Jeff Brown54bc2812010-06-15 01:31:58 -07002692
Jeff Browne57e8952010-07-23 21:28:06 -07002693 if (! mAxes.touchMinor.valid) {
2694 mAxes.touchMinor = mAxes.touchMajor;
Jeff Brown54bc2812010-06-15 01:31:58 -07002695 }
2696
Jeff Browne57e8952010-07-23 21:28:06 -07002697 if (! mAxes.toolMinor.valid) {
2698 mAxes.toolMinor = mAxes.toolMajor;
2699 }
Jeff Brown54bc2812010-06-15 01:31:58 -07002700
Jeff Browne57e8952010-07-23 21:28:06 -07002701 mAxes.pressure = mAxes.touchMajor;
2702 mAxes.size = mAxes.toolMajor;
Jeff Brown54bc2812010-06-15 01:31:58 -07002703}
2704
Jeff Browne839a582010-04-22 18:58:52 -07002705
2706} // namespace android