blob: 47cfa050306b5f89197465676e0e5be857f54f5c [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036#include "InputReader.h"
37
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080039#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080040#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070045#include <errno.h>
46#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070047#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048
Jeff Brown8d608662010-08-30 03:02:23 -070049#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070050#define INDENT2 " "
51#define INDENT3 " "
52#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070053
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070054namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60 return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65 return a < b ? a : b;
66}
67
Jeff Brown5c225b12010-06-16 01:53:36 -070068template<typename T>
69inline static void swap(T& a, T& b) {
70 T temp = a;
71 a = b;
72 b = temp;
73}
74
Jeff Brown8d608662010-08-30 03:02:23 -070075inline static float avg(float x, float y) {
76 return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80 return sqrtf(x * x + y * y);
81}
82
Jeff Brown517bb4c2011-01-14 19:09:23 -080083inline static int32_t signExtendNybble(int32_t value) {
84 return value >= 8 ? value - 16 : value;
85}
86
Jeff Brownef3d7e82010-09-30 14:33:04 -070087static inline const char* toString(bool value) {
88 return value ? "true" : "false";
89}
90
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070091static const int32_t keyCodeRotationMap[][4] = {
92 // key codes enumerated counter-clockwise with the original (unrotated) key first
93 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -070094 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
95 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
96 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
97 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070098};
99static const int keyCodeRotationMapSize =
100 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
101
102int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103 if (orientation != DISPLAY_ORIENTATION_0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700104 for (int i = 0; i < keyCodeRotationMapSize; i++) {
105 if (keyCode == keyCodeRotationMap[i][0]) {
106 return keyCodeRotationMap[i][orientation];
107 }
108 }
109 }
110 return keyCode;
111}
112
Jeff Brown6d0fec22010-07-23 21:28:06 -0700113static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
114 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
115}
116
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700117
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700118// --- InputReader ---
119
120InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700121 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700122 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700123 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brownfe508922011-01-18 15:10:10 -0800124 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700125 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700126 updateGlobalMetaState();
127 updateInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700128}
129
130InputReader::~InputReader() {
131 for (size_t i = 0; i < mDevices.size(); i++) {
132 delete mDevices.valueAt(i);
133 }
134}
135
136void InputReader::loopOnce() {
137 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700138 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700139
140#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800141 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700142 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
143 rawEvent.value);
144#endif
145
146 process(& rawEvent);
147}
148
149void InputReader::process(const RawEvent* rawEvent) {
150 switch (rawEvent->type) {
151 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700152 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700153 break;
154
155 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700156 removeDevice(rawEvent->deviceId);
157 break;
158
159 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700160 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700161 break;
162
Jeff Brown6d0fec22010-07-23 21:28:06 -0700163 default:
164 consumeEvent(rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700165 break;
166 }
167}
168
Jeff Brown7342bb92010-10-01 18:55:43 -0700169void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700170 String8 name = mEventHub->getDeviceName(deviceId);
171 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
172
173 InputDevice* device = createDevice(deviceId, name, classes);
174 device->configure();
175
Jeff Brown8d608662010-08-30 03:02:23 -0700176 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800177 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700178 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800179 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700180 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700181 }
182
Jeff Brown6d0fec22010-07-23 21:28:06 -0700183 bool added = false;
184 { // acquire device registry writer lock
185 RWLock::AutoWLock _wl(mDeviceRegistryLock);
186
187 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
188 if (deviceIndex < 0) {
189 mDevices.add(deviceId, device);
190 added = true;
191 }
192 } // release device registry writer lock
193
194 if (! added) {
195 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
196 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700197 return;
198 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700199}
200
Jeff Brown7342bb92010-10-01 18:55:43 -0700201void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700202 bool removed = false;
203 InputDevice* device = NULL;
204 { // acquire device registry writer lock
205 RWLock::AutoWLock _wl(mDeviceRegistryLock);
206
207 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
208 if (deviceIndex >= 0) {
209 device = mDevices.valueAt(deviceIndex);
210 mDevices.removeItemsAt(deviceIndex, 1);
211 removed = true;
212 }
213 } // release device registry writer lock
214
215 if (! removed) {
216 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800221 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 device->getId(), device->getName().string());
223 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800224 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700225 device->getId(), device->getName().string(), device->getSources());
226 }
227
Jeff Brown8d608662010-08-30 03:02:23 -0700228 device->reset();
229
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700231}
232
Jeff Brown6d0fec22010-07-23 21:28:06 -0700233InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
234 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700235
Jeff Brown6d0fec22010-07-23 21:28:06 -0700236 // Switch-like devices.
237 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
238 device->addMapper(new SwitchInputMapper(device));
239 }
240
241 // Keyboard-like devices.
242 uint32_t keyboardSources = 0;
243 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
244 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
245 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
246 }
247 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
248 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
249 }
250 if (classes & INPUT_DEVICE_CLASS_DPAD) {
251 keyboardSources |= AINPUT_SOURCE_DPAD;
252 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800253 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
254 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
255 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700256
257 if (keyboardSources != 0) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800258 device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700259 }
260
Jeff Brown83c09682010-12-23 17:50:18 -0800261 // Cursor-like devices.
262 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
263 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700264 }
265
Jeff Brown58a2da82011-01-25 16:02:22 -0800266 // Touchscreens and touchpad devices.
267 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800268 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800269 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800270 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700271 }
272
Jeff Browncb1404e2011-01-15 18:14:15 -0800273 // Joystick-like devices.
274 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
275 device->addMapper(new JoystickInputMapper(device));
276 }
277
Jeff Brown6d0fec22010-07-23 21:28:06 -0700278 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
Jeff Brownc3db8582010-10-20 15:33:38 -0700303void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700304 // Reset global meta state because it depends on the list of all configured devices.
305 updateGlobalMetaState();
306
307 // Update input configuration.
308 updateInputConfiguration();
309
310 // Enqueue configuration changed.
311 mDispatcher->notifyConfigurationChanged(when);
312}
313
314void InputReader::configureExcludedDevices() {
315 Vector<String8> excludedDeviceNames;
316 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
317
318 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
319 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
320 }
321}
322
323void InputReader::updateGlobalMetaState() {
324 { // acquire state lock
325 AutoMutex _l(mStateLock);
326
327 mGlobalMetaState = 0;
328
329 { // acquire device registry reader lock
330 RWLock::AutoRLock _rl(mDeviceRegistryLock);
331
332 for (size_t i = 0; i < mDevices.size(); i++) {
333 InputDevice* device = mDevices.valueAt(i);
334 mGlobalMetaState |= device->getMetaState();
335 }
336 } // release device registry reader lock
337 } // release state lock
338}
339
340int32_t InputReader::getGlobalMetaState() {
341 { // acquire state lock
342 AutoMutex _l(mStateLock);
343
344 return mGlobalMetaState;
345 } // release state lock
346}
347
348void InputReader::updateInputConfiguration() {
349 { // acquire state lock
350 AutoMutex _l(mStateLock);
351
352 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
353 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
354 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
355 { // acquire device registry reader lock
356 RWLock::AutoRLock _rl(mDeviceRegistryLock);
357
358 InputDeviceInfo deviceInfo;
359 for (size_t i = 0; i < mDevices.size(); i++) {
360 InputDevice* device = mDevices.valueAt(i);
361 device->getDeviceInfo(& deviceInfo);
362 uint32_t sources = deviceInfo.getSources();
363
364 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
365 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
366 }
367 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
368 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
369 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
370 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
371 }
372 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
373 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700374 }
375 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700377
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 mInputConfiguration.touchScreen = touchScreenConfig;
379 mInputConfiguration.keyboard = keyboardConfig;
380 mInputConfiguration.navigation = navigationConfig;
381 } // release state lock
382}
383
Jeff Brownfe508922011-01-18 15:10:10 -0800384void InputReader::disableVirtualKeysUntil(nsecs_t time) {
385 mDisableVirtualKeysTimeout = time;
386}
387
388bool InputReader::shouldDropVirtualKey(nsecs_t now,
389 InputDevice* device, int32_t keyCode, int32_t scanCode) {
390 if (now < mDisableVirtualKeysTimeout) {
391 LOGI("Dropping virtual key from device %s because virtual keys are "
392 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
393 device->getName().string(),
394 (mDisableVirtualKeysTimeout - now) * 0.000001,
395 keyCode, scanCode);
396 return true;
397 } else {
398 return false;
399 }
400}
401
Jeff Brown6d0fec22010-07-23 21:28:06 -0700402void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
403 { // acquire state lock
404 AutoMutex _l(mStateLock);
405
406 *outConfiguration = mInputConfiguration;
407 } // release state lock
408}
409
410status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
411 { // acquire device registry reader lock
412 RWLock::AutoRLock _rl(mDeviceRegistryLock);
413
414 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
415 if (deviceIndex < 0) {
416 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700417 }
418
Jeff Brown6d0fec22010-07-23 21:28:06 -0700419 InputDevice* device = mDevices.valueAt(deviceIndex);
420 if (device->isIgnored()) {
421 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700422 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700423
424 device->getDeviceInfo(outDeviceInfo);
425 return OK;
426 } // release device registy reader lock
427}
428
429void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
430 outDeviceIds.clear();
431
432 { // acquire device registry reader lock
433 RWLock::AutoRLock _rl(mDeviceRegistryLock);
434
435 size_t numDevices = mDevices.size();
436 for (size_t i = 0; i < numDevices; i++) {
437 InputDevice* device = mDevices.valueAt(i);
438 if (! device->isIgnored()) {
439 outDeviceIds.add(device->getId());
440 }
441 }
442 } // release device registy reader lock
443}
444
445int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
446 int32_t keyCode) {
447 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
448}
449
450int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
451 int32_t scanCode) {
452 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
453}
454
455int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
456 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
457}
458
459int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
460 GetStateFunc getStateFunc) {
461 { // acquire device registry reader lock
462 RWLock::AutoRLock _rl(mDeviceRegistryLock);
463
464 int32_t result = AKEY_STATE_UNKNOWN;
465 if (deviceId >= 0) {
466 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
467 if (deviceIndex >= 0) {
468 InputDevice* device = mDevices.valueAt(deviceIndex);
469 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
470 result = (device->*getStateFunc)(sourceMask, code);
471 }
472 }
473 } else {
474 size_t numDevices = mDevices.size();
475 for (size_t i = 0; i < numDevices; i++) {
476 InputDevice* device = mDevices.valueAt(i);
477 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
478 result = (device->*getStateFunc)(sourceMask, code);
479 if (result >= AKEY_STATE_DOWN) {
480 return result;
481 }
482 }
483 }
484 }
485 return result;
486 } // release device registy reader lock
487}
488
489bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
490 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
491 memset(outFlags, 0, numCodes);
492 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
493}
494
495bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
496 const int32_t* keyCodes, uint8_t* outFlags) {
497 { // acquire device registry reader lock
498 RWLock::AutoRLock _rl(mDeviceRegistryLock);
499 bool result = false;
500 if (deviceId >= 0) {
501 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
502 if (deviceIndex >= 0) {
503 InputDevice* device = mDevices.valueAt(deviceIndex);
504 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
505 result = device->markSupportedKeyCodes(sourceMask,
506 numCodes, keyCodes, outFlags);
507 }
508 }
509 } else {
510 size_t numDevices = mDevices.size();
511 for (size_t i = 0; i < numDevices; i++) {
512 InputDevice* device = mDevices.valueAt(i);
513 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
514 result |= device->markSupportedKeyCodes(sourceMask,
515 numCodes, keyCodes, outFlags);
516 }
517 }
518 }
519 return result;
520 } // release device registy reader lock
521}
522
Jeff Brownb88102f2010-09-08 11:49:43 -0700523void InputReader::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -0700524 mEventHub->dump(dump);
525 dump.append("\n");
526
527 dump.append("Input Reader State:\n");
528
Jeff Brownef3d7e82010-09-30 14:33:04 -0700529 { // acquire device registry reader lock
530 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700531
Jeff Brownef3d7e82010-09-30 14:33:04 -0700532 for (size_t i = 0; i < mDevices.size(); i++) {
533 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700534 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700535 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700536}
537
Jeff Brown6d0fec22010-07-23 21:28:06 -0700538
539// --- InputReaderThread ---
540
541InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
542 Thread(/*canCallJava*/ true), mReader(reader) {
543}
544
545InputReaderThread::~InputReaderThread() {
546}
547
548bool InputReaderThread::threadLoop() {
549 mReader->loopOnce();
550 return true;
551}
552
553
554// --- InputDevice ---
555
556InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
557 mContext(context), mId(id), mName(name), mSources(0) {
558}
559
560InputDevice::~InputDevice() {
561 size_t numMappers = mMappers.size();
562 for (size_t i = 0; i < numMappers; i++) {
563 delete mMappers[i];
564 }
565 mMappers.clear();
566}
567
Jeff Brownef3d7e82010-09-30 14:33:04 -0700568static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
569 int32_t rangeType, const char* name) {
570 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
571 if (range) {
572 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
573 name, range->min, range->max, range->flat, range->fuzz);
574 }
575}
576
577void InputDevice::dump(String8& dump) {
578 InputDeviceInfo deviceInfo;
579 getDeviceInfo(& deviceInfo);
580
Jeff Brown90655042010-12-02 13:50:46 -0800581 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700582 deviceInfo.getName().string());
583 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
584 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
585 if (!deviceInfo.getMotionRanges().isEmpty()) {
586 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Brown6f2fba42011-02-19 01:08:02 -0800587 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_X, "X");
588 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_Y, "Y");
589 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_PRESSURE, "Pressure");
590 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_SIZE, "Size");
591 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOUCH_MAJOR, "TouchMajor");
592 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOUCH_MINOR, "TouchMinor");
593 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOOL_MAJOR, "ToolMajor");
594 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_TOOL_MINOR, "ToolMinor");
595 dumpMotionRange(dump, deviceInfo, AMOTION_EVENT_AXIS_ORIENTATION, "Orientation");
Jeff Brownef3d7e82010-09-30 14:33:04 -0700596 }
597
598 size_t numMappers = mMappers.size();
599 for (size_t i = 0; i < numMappers; i++) {
600 InputMapper* mapper = mMappers[i];
601 mapper->dump(dump);
602 }
603}
604
Jeff Brown6d0fec22010-07-23 21:28:06 -0700605void InputDevice::addMapper(InputMapper* mapper) {
606 mMappers.add(mapper);
607}
608
609void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700610 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800611 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700612 }
613
Jeff Brown6d0fec22010-07-23 21:28:06 -0700614 mSources = 0;
615
616 size_t numMappers = mMappers.size();
617 for (size_t i = 0; i < numMappers; i++) {
618 InputMapper* mapper = mMappers[i];
619 mapper->configure();
620 mSources |= mapper->getSources();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700621 }
622}
623
Jeff Brown6d0fec22010-07-23 21:28:06 -0700624void InputDevice::reset() {
625 size_t numMappers = mMappers.size();
626 for (size_t i = 0; i < numMappers; i++) {
627 InputMapper* mapper = mMappers[i];
628 mapper->reset();
629 }
630}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700631
Jeff Brown6d0fec22010-07-23 21:28:06 -0700632void InputDevice::process(const RawEvent* rawEvent) {
633 size_t numMappers = mMappers.size();
634 for (size_t i = 0; i < numMappers; i++) {
635 InputMapper* mapper = mMappers[i];
636 mapper->process(rawEvent);
637 }
638}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700639
Jeff Brown6d0fec22010-07-23 21:28:06 -0700640void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
641 outDeviceInfo->initialize(mId, mName);
642
643 size_t numMappers = mMappers.size();
644 for (size_t i = 0; i < numMappers; i++) {
645 InputMapper* mapper = mMappers[i];
646 mapper->populateDeviceInfo(outDeviceInfo);
647 }
648}
649
650int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
651 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
652}
653
654int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
655 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
656}
657
658int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
659 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
660}
661
662int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
663 int32_t result = AKEY_STATE_UNKNOWN;
664 size_t numMappers = mMappers.size();
665 for (size_t i = 0; i < numMappers; i++) {
666 InputMapper* mapper = mMappers[i];
667 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
668 result = (mapper->*getStateFunc)(sourceMask, code);
669 if (result >= AKEY_STATE_DOWN) {
670 return result;
671 }
672 }
673 }
674 return result;
675}
676
677bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
678 const int32_t* keyCodes, uint8_t* outFlags) {
679 bool result = false;
680 size_t numMappers = mMappers.size();
681 for (size_t i = 0; i < numMappers; i++) {
682 InputMapper* mapper = mMappers[i];
683 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
684 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
685 }
686 }
687 return result;
688}
689
690int32_t InputDevice::getMetaState() {
691 int32_t result = 0;
692 size_t numMappers = mMappers.size();
693 for (size_t i = 0; i < numMappers; i++) {
694 InputMapper* mapper = mMappers[i];
695 result |= mapper->getMetaState();
696 }
697 return result;
698}
699
700
701// --- InputMapper ---
702
703InputMapper::InputMapper(InputDevice* device) :
704 mDevice(device), mContext(device->getContext()) {
705}
706
707InputMapper::~InputMapper() {
708}
709
710void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
711 info->addSource(getSources());
712}
713
Jeff Brownef3d7e82010-09-30 14:33:04 -0700714void InputMapper::dump(String8& dump) {
715}
716
Jeff Brown6d0fec22010-07-23 21:28:06 -0700717void InputMapper::configure() {
718}
719
720void InputMapper::reset() {
721}
722
723int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
724 return AKEY_STATE_UNKNOWN;
725}
726
727int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
728 return AKEY_STATE_UNKNOWN;
729}
730
731int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
732 return AKEY_STATE_UNKNOWN;
733}
734
735bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
736 const int32_t* keyCodes, uint8_t* outFlags) {
737 return false;
738}
739
740int32_t InputMapper::getMetaState() {
741 return 0;
742}
743
Jeff Browncb1404e2011-01-15 18:14:15 -0800744void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
745 const RawAbsoluteAxisInfo& axis, const char* name) {
746 if (axis.valid) {
747 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
748 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
749 } else {
750 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
751 }
752}
753
Jeff Brown6d0fec22010-07-23 21:28:06 -0700754
755// --- SwitchInputMapper ---
756
757SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
758 InputMapper(device) {
759}
760
761SwitchInputMapper::~SwitchInputMapper() {
762}
763
764uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800765 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700766}
767
768void SwitchInputMapper::process(const RawEvent* rawEvent) {
769 switch (rawEvent->type) {
770 case EV_SW:
771 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
772 break;
773 }
774}
775
776void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700777 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700778}
779
780int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
781 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
782}
783
784
785// --- KeyboardInputMapper ---
786
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800787KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700788 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800789 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700790 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700791 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700792}
793
794KeyboardInputMapper::~KeyboardInputMapper() {
795}
796
Jeff Brown6328cdc2010-07-29 18:18:33 -0700797void KeyboardInputMapper::initializeLocked() {
798 mLocked.metaState = AMETA_NONE;
799 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700800}
801
802uint32_t KeyboardInputMapper::getSources() {
803 return mSources;
804}
805
806void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
807 InputMapper::populateDeviceInfo(info);
808
809 info->setKeyboardType(mKeyboardType);
810}
811
Jeff Brownef3d7e82010-09-30 14:33:04 -0700812void KeyboardInputMapper::dump(String8& dump) {
813 { // acquire lock
814 AutoMutex _l(mLock);
815 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800816 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700817 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
818 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
819 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
820 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
821 } // release lock
822}
823
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800824
825void KeyboardInputMapper::configure() {
826 InputMapper::configure();
827
828 // Configure basic parameters.
829 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800830
831 // Reset LEDs.
832 {
833 AutoMutex _l(mLock);
834 resetLedStateLocked();
835 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800836}
837
838void KeyboardInputMapper::configureParameters() {
839 mParameters.orientationAware = false;
840 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
841 mParameters.orientationAware);
842
843 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
844}
845
846void KeyboardInputMapper::dumpParameters(String8& dump) {
847 dump.append(INDENT3 "Parameters:\n");
848 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
849 mParameters.associatedDisplayId);
850 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
851 toString(mParameters.orientationAware));
852}
853
Jeff Brown6d0fec22010-07-23 21:28:06 -0700854void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700855 for (;;) {
856 int32_t keyCode, scanCode;
857 { // acquire lock
858 AutoMutex _l(mLock);
859
860 // Synthesize key up event on reset if keys are currently down.
861 if (mLocked.keyDowns.isEmpty()) {
862 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800863 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700864 break; // done
865 }
866
867 const KeyDown& keyDown = mLocked.keyDowns.top();
868 keyCode = keyDown.keyCode;
869 scanCode = keyDown.scanCode;
870 } // release lock
871
Jeff Brown6d0fec22010-07-23 21:28:06 -0700872 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700873 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700874 }
875
876 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700877 getContext()->updateGlobalMetaState();
878}
879
880void KeyboardInputMapper::process(const RawEvent* rawEvent) {
881 switch (rawEvent->type) {
882 case EV_KEY: {
883 int32_t scanCode = rawEvent->scanCode;
884 if (isKeyboardOrGamepadKey(scanCode)) {
885 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
886 rawEvent->flags);
887 }
888 break;
889 }
890 }
891}
892
893bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
894 return scanCode < BTN_MOUSE
895 || scanCode >= KEY_OK
Jeff Browncb1404e2011-01-15 18:14:15 -0800896 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700897}
898
Jeff Brown6328cdc2010-07-29 18:18:33 -0700899void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
900 int32_t scanCode, uint32_t policyFlags) {
901 int32_t newMetaState;
902 nsecs_t downTime;
903 bool metaStateChanged = false;
904
905 { // acquire lock
906 AutoMutex _l(mLock);
907
908 if (down) {
909 // Rotate key codes according to orientation if needed.
910 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800911 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700912 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800913 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
914 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800915 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700916 }
917
918 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700919 }
920
Jeff Brown6328cdc2010-07-29 18:18:33 -0700921 // Add key down.
922 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
923 if (keyDownIndex >= 0) {
924 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800925 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700926 } else {
927 // key down
Jeff Brownfe508922011-01-18 15:10:10 -0800928 if ((policyFlags & POLICY_FLAG_VIRTUAL)
929 && mContext->shouldDropVirtualKey(when,
930 getDevice(), keyCode, scanCode)) {
931 return;
932 }
933
Jeff Brown6328cdc2010-07-29 18:18:33 -0700934 mLocked.keyDowns.push();
935 KeyDown& keyDown = mLocked.keyDowns.editTop();
936 keyDown.keyCode = keyCode;
937 keyDown.scanCode = scanCode;
938 }
939
940 mLocked.downTime = when;
941 } else {
942 // Remove key down.
943 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
944 if (keyDownIndex >= 0) {
945 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800946 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700947 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
948 } else {
949 // key was not actually down
950 LOGI("Dropping key up from device %s because the key was not down. "
951 "keyCode=%d, scanCode=%d",
952 getDeviceName().string(), keyCode, scanCode);
953 return;
954 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700955 }
956
Jeff Brown6328cdc2010-07-29 18:18:33 -0700957 int32_t oldMetaState = mLocked.metaState;
958 newMetaState = updateMetaState(keyCode, down, oldMetaState);
959 if (oldMetaState != newMetaState) {
960 mLocked.metaState = newMetaState;
961 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -0700962 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700963 }
Jeff Brownfd0358292010-06-30 16:10:35 -0700964
Jeff Brown6328cdc2010-07-29 18:18:33 -0700965 downTime = mLocked.downTime;
966 } // release lock
967
968 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700969 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700970 }
971
Jeff Brown497a92c2010-09-12 17:55:08 -0700972 if (policyFlags & POLICY_FLAG_FUNCTION) {
973 newMetaState |= AMETA_FUNCTION_ON;
974 }
Jeff Brown83c09682010-12-23 17:50:18 -0800975 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -0700976 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
977 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700978}
979
Jeff Brown6328cdc2010-07-29 18:18:33 -0700980ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
981 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700982 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700983 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700984 return i;
985 }
986 }
987 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700988}
989
Jeff Brown6d0fec22010-07-23 21:28:06 -0700990int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
991 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
992}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700993
Jeff Brown6d0fec22010-07-23 21:28:06 -0700994int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
995 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
996}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700997
Jeff Brown6d0fec22010-07-23 21:28:06 -0700998bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
999 const int32_t* keyCodes, uint8_t* outFlags) {
1000 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1001}
1002
1003int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001004 { // acquire lock
1005 AutoMutex _l(mLock);
1006 return mLocked.metaState;
1007 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001008}
1009
Jeff Brown49ed71d2010-12-06 17:13:33 -08001010void KeyboardInputMapper::resetLedStateLocked() {
1011 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1012 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1013 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1014
1015 updateLedStateLocked(true);
1016}
1017
1018void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1019 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1020 ledState.on = false;
1021}
1022
Jeff Brown497a92c2010-09-12 17:55:08 -07001023void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1024 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001025 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001026 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001027 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001028 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001029 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001030}
1031
1032void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1033 int32_t led, int32_t modifier, bool reset) {
1034 if (ledState.avail) {
1035 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001036 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001037 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1038 ledState.on = desiredState;
1039 }
1040 }
1041}
1042
Jeff Brown6d0fec22010-07-23 21:28:06 -07001043
Jeff Brown83c09682010-12-23 17:50:18 -08001044// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001045
Jeff Brown83c09682010-12-23 17:50:18 -08001046CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001047 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001048 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001049}
1050
Jeff Brown83c09682010-12-23 17:50:18 -08001051CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001052}
1053
Jeff Brown83c09682010-12-23 17:50:18 -08001054uint32_t CursorInputMapper::getSources() {
1055 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001056}
1057
Jeff Brown83c09682010-12-23 17:50:18 -08001058void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001059 InputMapper::populateDeviceInfo(info);
1060
Jeff Brown83c09682010-12-23 17:50:18 -08001061 if (mParameters.mode == Parameters::MODE_POINTER) {
1062 float minX, minY, maxX, maxY;
1063 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001064 info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
1065 info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001066 }
1067 } else {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001068 info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
1069 info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001070 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001071 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
1072
1073 if (mHaveVWheel) {
1074 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1075 }
1076 if (mHaveHWheel) {
1077 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1078 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001079}
1080
Jeff Brown83c09682010-12-23 17:50:18 -08001081void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001082 { // acquire lock
1083 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001084 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001085 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001086 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1087 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001088 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1089 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001090 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1091 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1092 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1093 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001094 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1095 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1096 } // release lock
1097}
1098
Jeff Brown83c09682010-12-23 17:50:18 -08001099void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001100 InputMapper::configure();
1101
1102 // Configure basic parameters.
1103 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001104
1105 // Configure device mode.
1106 switch (mParameters.mode) {
1107 case Parameters::MODE_POINTER:
1108 mSources = AINPUT_SOURCE_MOUSE;
1109 mXPrecision = 1.0f;
1110 mYPrecision = 1.0f;
1111 mXScale = 1.0f;
1112 mYScale = 1.0f;
1113 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1114 break;
1115 case Parameters::MODE_NAVIGATION:
1116 mSources = AINPUT_SOURCE_TRACKBALL;
1117 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1118 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1119 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1120 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1121 break;
1122 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001123
1124 mVWheelScale = 1.0f;
1125 mHWheelScale = 1.0f;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001126}
1127
Jeff Brown83c09682010-12-23 17:50:18 -08001128void CursorInputMapper::configureParameters() {
1129 mParameters.mode = Parameters::MODE_POINTER;
1130 String8 cursorModeString;
1131 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1132 if (cursorModeString == "navigation") {
1133 mParameters.mode = Parameters::MODE_NAVIGATION;
1134 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1135 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1136 }
1137 }
1138
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001139 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001140 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001141 mParameters.orientationAware);
1142
Jeff Brown83c09682010-12-23 17:50:18 -08001143 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1144 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001145}
1146
Jeff Brown83c09682010-12-23 17:50:18 -08001147void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001148 dump.append(INDENT3 "Parameters:\n");
1149 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1150 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001151
1152 switch (mParameters.mode) {
1153 case Parameters::MODE_POINTER:
1154 dump.append(INDENT4 "Mode: pointer\n");
1155 break;
1156 case Parameters::MODE_NAVIGATION:
1157 dump.append(INDENT4 "Mode: navigation\n");
1158 break;
1159 default:
1160 assert(false);
1161 }
1162
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001163 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1164 toString(mParameters.orientationAware));
1165}
1166
Jeff Brown83c09682010-12-23 17:50:18 -08001167void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001168 mAccumulator.clear();
1169
Jeff Brown6328cdc2010-07-29 18:18:33 -07001170 mLocked.down = false;
1171 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001172}
1173
Jeff Brown83c09682010-12-23 17:50:18 -08001174void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001175 for (;;) {
1176 { // acquire lock
1177 AutoMutex _l(mLock);
1178
1179 if (! mLocked.down) {
1180 initializeLocked();
1181 break; // done
1182 }
1183 } // release lock
1184
Jeff Brown83c09682010-12-23 17:50:18 -08001185 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001186 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001187 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001188 mAccumulator.btnMouse = false;
1189 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001190 }
1191
Jeff Brown6d0fec22010-07-23 21:28:06 -07001192 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001193}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001194
Jeff Brown83c09682010-12-23 17:50:18 -08001195void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001196 switch (rawEvent->type) {
1197 case EV_KEY:
1198 switch (rawEvent->scanCode) {
1199 case BTN_MOUSE:
1200 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1201 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001202 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1203 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001204 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001205 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001206 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001207 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001208
Jeff Brown6d0fec22010-07-23 21:28:06 -07001209 case EV_REL:
1210 switch (rawEvent->scanCode) {
1211 case REL_X:
1212 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1213 mAccumulator.relX = rawEvent->value;
1214 break;
1215 case REL_Y:
1216 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1217 mAccumulator.relY = rawEvent->value;
1218 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001219 case REL_WHEEL:
1220 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1221 mAccumulator.relWheel = rawEvent->value;
1222 break;
1223 case REL_HWHEEL:
1224 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1225 mAccumulator.relHWheel = rawEvent->value;
1226 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001227 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001228 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001229
Jeff Brown6d0fec22010-07-23 21:28:06 -07001230 case EV_SYN:
1231 switch (rawEvent->scanCode) {
1232 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001233 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001234 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001235 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001236 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001237 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001238}
1239
Jeff Brown83c09682010-12-23 17:50:18 -08001240void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001241 uint32_t fields = mAccumulator.fields;
1242 if (fields == 0) {
1243 return; // no new state changes, so nothing to do
1244 }
1245
Jeff Brown6328cdc2010-07-29 18:18:33 -07001246 int motionEventAction;
1247 PointerCoords pointerCoords;
1248 nsecs_t downTime;
1249 { // acquire lock
1250 AutoMutex _l(mLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001251
Jeff Brown6328cdc2010-07-29 18:18:33 -07001252 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1253
1254 if (downChanged) {
1255 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001256 if (!mLocked.down) {
1257 mLocked.down = true;
1258 mLocked.downTime = when;
1259 } else {
1260 downChanged = false;
1261 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001262 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001263 if (mLocked.down) {
1264 mLocked.down = false;
1265 } else {
1266 downChanged = false;
1267 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001268 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001269 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001270
Jeff Brown6328cdc2010-07-29 18:18:33 -07001271 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001272 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1273 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001274
Jeff Brown6328cdc2010-07-29 18:18:33 -07001275 if (downChanged) {
1276 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001277 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001278 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001279 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001280
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001281 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001282 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001283 // Rotate motion based on display orientation if needed.
1284 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1285 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001286 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1287 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001288 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001289 }
1290
1291 float temp;
1292 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001293 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001294 temp = deltaX;
1295 deltaX = deltaY;
1296 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001297 break;
1298
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001299 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001300 deltaX = -deltaX;
1301 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001302 break;
1303
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001304 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001305 temp = deltaX;
1306 deltaX = -deltaY;
1307 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001308 break;
1309 }
1310 }
Jeff Brown83c09682010-12-23 17:50:18 -08001311
Jeff Brown91c69ab2011-02-14 17:03:18 -08001312 pointerCoords.clear();
1313
Jeff Brown83c09682010-12-23 17:50:18 -08001314 if (mPointerController != NULL) {
1315 mPointerController->move(deltaX, deltaY);
1316 if (downChanged) {
1317 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1318 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08001319 float x, y;
1320 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001321 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1322 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown83c09682010-12-23 17:50:18 -08001323 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001324 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1325 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001326 }
1327
Jeff Brownebbd5d12011-02-17 13:01:34 -08001328 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001329
1330 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1331 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, mAccumulator.relWheel);
1332 }
1333 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1334 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, mAccumulator.relHWheel);
1335 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001336 } // release lock
1337
Jeff Brown6d0fec22010-07-23 21:28:06 -07001338 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001339 int32_t pointerId = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001340 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
Jeff Brown85a31762010-09-01 17:01:00 -07001341 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001342 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1343
1344 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001345}
1346
Jeff Brown83c09682010-12-23 17:50:18 -08001347int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001348 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1349 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1350 } else {
1351 return AKEY_STATE_UNKNOWN;
1352 }
1353}
1354
Jeff Brown6d0fec22010-07-23 21:28:06 -07001355
1356// --- TouchInputMapper ---
1357
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001358TouchInputMapper::TouchInputMapper(InputDevice* device) :
1359 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001360 mLocked.surfaceOrientation = -1;
1361 mLocked.surfaceWidth = -1;
1362 mLocked.surfaceHeight = -1;
1363
1364 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001365}
1366
1367TouchInputMapper::~TouchInputMapper() {
1368}
1369
1370uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001371 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001372}
1373
1374void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1375 InputMapper::populateDeviceInfo(info);
1376
Jeff Brown6328cdc2010-07-29 18:18:33 -07001377 { // acquire lock
1378 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001379
Jeff Brown6328cdc2010-07-29 18:18:33 -07001380 // Ensure surface information is up to date so that orientation changes are
1381 // noticed immediately.
1382 configureSurfaceLocked();
1383
Jeff Brown6f2fba42011-02-19 01:08:02 -08001384 info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1385 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001386
1387 if (mLocked.orientedRanges.havePressure) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001388 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown8d608662010-08-30 03:02:23 -07001389 mLocked.orientedRanges.pressure);
1390 }
1391
1392 if (mLocked.orientedRanges.haveSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001393 info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown8d608662010-08-30 03:02:23 -07001394 mLocked.orientedRanges.size);
1395 }
1396
Jeff Brownc6d282b2010-10-14 21:42:15 -07001397 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001398 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001399 mLocked.orientedRanges.touchMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001400 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001401 mLocked.orientedRanges.touchMinor);
1402 }
1403
Jeff Brownc6d282b2010-10-14 21:42:15 -07001404 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001405 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001406 mLocked.orientedRanges.toolMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001407 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001408 mLocked.orientedRanges.toolMinor);
1409 }
1410
1411 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001412 info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown8d608662010-08-30 03:02:23 -07001413 mLocked.orientedRanges.orientation);
1414 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001415 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001416}
1417
Jeff Brownef3d7e82010-09-30 14:33:04 -07001418void TouchInputMapper::dump(String8& dump) {
1419 { // acquire lock
1420 AutoMutex _l(mLock);
1421 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001422 dumpParameters(dump);
1423 dumpVirtualKeysLocked(dump);
1424 dumpRawAxes(dump);
1425 dumpCalibration(dump);
1426 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001427 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001428 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1429 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1430 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1431 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1432 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1433 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1434 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1435 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1436 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1437 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1438 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1439 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1440 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1441 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001442 } // release lock
1443}
1444
Jeff Brown6328cdc2010-07-29 18:18:33 -07001445void TouchInputMapper::initializeLocked() {
1446 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001447 mLastTouch.clear();
1448 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001449
1450 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1451 mAveragingTouchFilter.historyStart[i] = 0;
1452 mAveragingTouchFilter.historyEnd[i] = 0;
1453 }
1454
1455 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001456
1457 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001458
1459 mLocked.orientedRanges.havePressure = false;
1460 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001461 mLocked.orientedRanges.haveTouchSize = false;
1462 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001463 mLocked.orientedRanges.haveOrientation = false;
1464}
1465
Jeff Brown6d0fec22010-07-23 21:28:06 -07001466void TouchInputMapper::configure() {
1467 InputMapper::configure();
1468
1469 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001470 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001471
Jeff Brown83c09682010-12-23 17:50:18 -08001472 // Configure sources.
1473 switch (mParameters.deviceType) {
1474 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1475 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1476 break;
1477 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1478 mSources = AINPUT_SOURCE_TOUCHPAD;
1479 break;
1480 default:
1481 assert(false);
1482 }
1483
Jeff Brown6d0fec22010-07-23 21:28:06 -07001484 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001485 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001486
1487 // Prepare input device calibration.
1488 parseCalibration();
1489 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001490
Jeff Brown6328cdc2010-07-29 18:18:33 -07001491 { // acquire lock
1492 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001493
Jeff Brown8d608662010-08-30 03:02:23 -07001494 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001495 configureSurfaceLocked();
1496 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001497}
1498
Jeff Brown8d608662010-08-30 03:02:23 -07001499void TouchInputMapper::configureParameters() {
1500 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1501 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1502 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001503 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001504
1505 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001506 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001507 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1508 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001509 if (deviceTypeString == "touchScreen") {
1510 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1511 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001512 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1513 }
1514 }
1515 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1516
1517 mParameters.orientationAware = isTouchScreen;
1518 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1519 mParameters.orientationAware);
1520
1521 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001522}
1523
Jeff Brownef3d7e82010-09-30 14:33:04 -07001524void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001525 dump.append(INDENT3 "Parameters:\n");
1526
1527 switch (mParameters.deviceType) {
1528 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1529 dump.append(INDENT4 "DeviceType: touchScreen\n");
1530 break;
1531 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1532 dump.append(INDENT4 "DeviceType: touchPad\n");
1533 break;
1534 default:
1535 assert(false);
1536 }
1537
1538 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1539 mParameters.associatedDisplayId);
1540 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1541 toString(mParameters.orientationAware));
1542
1543 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001544 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001545 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001546 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001547 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001548 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001549}
1550
Jeff Brown8d608662010-08-30 03:02:23 -07001551void TouchInputMapper::configureRawAxes() {
1552 mRawAxes.x.clear();
1553 mRawAxes.y.clear();
1554 mRawAxes.pressure.clear();
1555 mRawAxes.touchMajor.clear();
1556 mRawAxes.touchMinor.clear();
1557 mRawAxes.toolMajor.clear();
1558 mRawAxes.toolMinor.clear();
1559 mRawAxes.orientation.clear();
1560}
1561
Jeff Brownef3d7e82010-09-30 14:33:04 -07001562void TouchInputMapper::dumpRawAxes(String8& dump) {
1563 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001564 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1565 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1566 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1567 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1568 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1569 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1570 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1571 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001572}
1573
Jeff Brown6328cdc2010-07-29 18:18:33 -07001574bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001575 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001576 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001577 int32_t width = mRawAxes.x.getRange();
1578 int32_t height = mRawAxes.y.getRange();
1579
1580 if (mParameters.associatedDisplayId >= 0) {
1581 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1582 bool wantOrientation = mParameters.orientationAware;
1583
Jeff Brown6328cdc2010-07-29 18:18:33 -07001584 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001585 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1586 wantSize ? &width : NULL, wantSize ? &height : NULL,
1587 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001588 return false;
1589 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001590 }
1591
Jeff Brown6328cdc2010-07-29 18:18:33 -07001592 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001593 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001594 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001595 }
1596
Jeff Brown6328cdc2010-07-29 18:18:33 -07001597 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001598 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001599 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001600 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001601
Jeff Brown6328cdc2010-07-29 18:18:33 -07001602 mLocked.surfaceWidth = width;
1603 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001604
Jeff Brown8d608662010-08-30 03:02:23 -07001605 // Configure X and Y factors.
1606 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001607 mLocked.xOrigin = mCalibration.haveXOrigin
1608 ? mCalibration.xOrigin
1609 : mRawAxes.x.minValue;
1610 mLocked.yOrigin = mCalibration.haveYOrigin
1611 ? mCalibration.yOrigin
1612 : mRawAxes.y.minValue;
1613 mLocked.xScale = mCalibration.haveXScale
1614 ? mCalibration.xScale
1615 : float(width) / mRawAxes.x.getRange();
1616 mLocked.yScale = mCalibration.haveYScale
1617 ? mCalibration.yScale
1618 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001619 mLocked.xPrecision = 1.0f / mLocked.xScale;
1620 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001621
Jeff Brown6328cdc2010-07-29 18:18:33 -07001622 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001623 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001624 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001625 mLocked.xOrigin = 0;
1626 mLocked.yOrigin = 0;
1627 mLocked.xScale = 1.0f;
1628 mLocked.yScale = 1.0f;
1629 mLocked.xPrecision = 1.0f;
1630 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001631 }
1632
Jeff Brown8d608662010-08-30 03:02:23 -07001633 // Scale factor for terms that are not oriented in a particular axis.
1634 // If the pixels are square then xScale == yScale otherwise we fake it
1635 // by choosing an average.
1636 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001637
Jeff Brown8d608662010-08-30 03:02:23 -07001638 // Size of diagonal axis.
1639 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001640
Jeff Brown8d608662010-08-30 03:02:23 -07001641 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001642 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1643 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001644 mLocked.orientedRanges.touchMajor.min = 0;
1645 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1646 mLocked.orientedRanges.touchMajor.flat = 0;
1647 mLocked.orientedRanges.touchMajor.fuzz = 0;
1648 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1649 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001650
Jeff Brown8d608662010-08-30 03:02:23 -07001651 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001652 mLocked.toolSizeLinearScale = 0;
1653 mLocked.toolSizeLinearBias = 0;
1654 mLocked.toolSizeAreaScale = 0;
1655 mLocked.toolSizeAreaBias = 0;
1656 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1657 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1658 if (mCalibration.haveToolSizeLinearScale) {
1659 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001660 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001661 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001662 / mRawAxes.toolMajor.maxValue;
1663 }
1664
Jeff Brownc6d282b2010-10-14 21:42:15 -07001665 if (mCalibration.haveToolSizeLinearBias) {
1666 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1667 }
1668 } else if (mCalibration.toolSizeCalibration ==
1669 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1670 if (mCalibration.haveToolSizeLinearScale) {
1671 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1672 } else {
1673 mLocked.toolSizeLinearScale = min(width, height);
1674 }
1675
1676 if (mCalibration.haveToolSizeLinearBias) {
1677 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1678 }
1679
1680 if (mCalibration.haveToolSizeAreaScale) {
1681 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1682 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1683 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1684 }
1685
1686 if (mCalibration.haveToolSizeAreaBias) {
1687 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001688 }
1689 }
1690
Jeff Brownc6d282b2010-10-14 21:42:15 -07001691 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001692 mLocked.orientedRanges.toolMajor.min = 0;
1693 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1694 mLocked.orientedRanges.toolMajor.flat = 0;
1695 mLocked.orientedRanges.toolMajor.fuzz = 0;
1696 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1697 }
1698
1699 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001700 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001701 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1702 RawAbsoluteAxisInfo rawPressureAxis;
1703 switch (mCalibration.pressureSource) {
1704 case Calibration::PRESSURE_SOURCE_PRESSURE:
1705 rawPressureAxis = mRawAxes.pressure;
1706 break;
1707 case Calibration::PRESSURE_SOURCE_TOUCH:
1708 rawPressureAxis = mRawAxes.touchMajor;
1709 break;
1710 default:
1711 rawPressureAxis.clear();
1712 }
1713
Jeff Brown8d608662010-08-30 03:02:23 -07001714 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1715 || mCalibration.pressureCalibration
1716 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1717 if (mCalibration.havePressureScale) {
1718 mLocked.pressureScale = mCalibration.pressureScale;
1719 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1720 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1721 }
1722 }
1723
1724 mLocked.orientedRanges.havePressure = true;
1725 mLocked.orientedRanges.pressure.min = 0;
1726 mLocked.orientedRanges.pressure.max = 1.0;
1727 mLocked.orientedRanges.pressure.flat = 0;
1728 mLocked.orientedRanges.pressure.fuzz = 0;
1729 }
1730
1731 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001732 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001733 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001734 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1735 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1736 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1737 }
1738 }
1739
1740 mLocked.orientedRanges.haveSize = true;
1741 mLocked.orientedRanges.size.min = 0;
1742 mLocked.orientedRanges.size.max = 1.0;
1743 mLocked.orientedRanges.size.flat = 0;
1744 mLocked.orientedRanges.size.fuzz = 0;
1745 }
1746
1747 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001748 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001749 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001750 if (mCalibration.orientationCalibration
1751 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1752 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1753 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1754 }
1755 }
1756
1757 mLocked.orientedRanges.orientation.min = - M_PI_2;
1758 mLocked.orientedRanges.orientation.max = M_PI_2;
1759 mLocked.orientedRanges.orientation.flat = 0;
1760 mLocked.orientedRanges.orientation.fuzz = 0;
1761 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001762 }
1763
1764 if (orientationChanged || sizeChanged) {
1765 // Compute oriented surface dimensions, precision, and scales.
1766 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001767 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001768 case DISPLAY_ORIENTATION_90:
1769 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001770 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1771 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1772 mLocked.orientedXPrecision = mLocked.yPrecision;
1773 mLocked.orientedYPrecision = mLocked.xPrecision;
1774 orientedXScale = mLocked.yScale;
1775 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001776 break;
1777 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001778 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1779 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1780 mLocked.orientedXPrecision = mLocked.xPrecision;
1781 mLocked.orientedYPrecision = mLocked.yPrecision;
1782 orientedXScale = mLocked.xScale;
1783 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001784 break;
1785 }
1786
1787 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001788 mLocked.orientedRanges.x.min = 0;
1789 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1790 mLocked.orientedRanges.x.flat = 0;
1791 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001792
Jeff Brown6328cdc2010-07-29 18:18:33 -07001793 mLocked.orientedRanges.y.min = 0;
1794 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1795 mLocked.orientedRanges.y.flat = 0;
1796 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001797 }
1798
1799 return true;
1800}
1801
Jeff Brownef3d7e82010-09-30 14:33:04 -07001802void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1803 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1804 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1805 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001806}
1807
Jeff Brown6328cdc2010-07-29 18:18:33 -07001808void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001809 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001810
Jeff Brown8d608662010-08-30 03:02:23 -07001811 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001812 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001813
Jeff Brown6328cdc2010-07-29 18:18:33 -07001814 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001815
Jeff Brown6328cdc2010-07-29 18:18:33 -07001816 if (virtualKeyDefinitions.size() == 0) {
1817 return;
1818 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001819
Jeff Brown6328cdc2010-07-29 18:18:33 -07001820 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1821
Jeff Brown8d608662010-08-30 03:02:23 -07001822 int32_t touchScreenLeft = mRawAxes.x.minValue;
1823 int32_t touchScreenTop = mRawAxes.y.minValue;
1824 int32_t touchScreenWidth = mRawAxes.x.getRange();
1825 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001826
1827 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001828 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001829 virtualKeyDefinitions[i];
1830
1831 mLocked.virtualKeys.add();
1832 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1833
1834 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1835 int32_t keyCode;
1836 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001837 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001838 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001839 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1840 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001841 mLocked.virtualKeys.pop(); // drop the key
1842 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001843 }
1844
Jeff Brown6328cdc2010-07-29 18:18:33 -07001845 virtualKey.keyCode = keyCode;
1846 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001847
Jeff Brown6328cdc2010-07-29 18:18:33 -07001848 // convert the key definition's display coordinates into touch coordinates for a hit box
1849 int32_t halfWidth = virtualKeyDefinition.width / 2;
1850 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001851
Jeff Brown6328cdc2010-07-29 18:18:33 -07001852 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1853 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1854 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1855 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1856 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1857 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1858 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1859 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001860
Jeff Brownef3d7e82010-09-30 14:33:04 -07001861 }
1862}
1863
1864void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1865 if (!mLocked.virtualKeys.isEmpty()) {
1866 dump.append(INDENT3 "Virtual Keys:\n");
1867
1868 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1869 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1870 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1871 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1872 i, virtualKey.scanCode, virtualKey.keyCode,
1873 virtualKey.hitLeft, virtualKey.hitRight,
1874 virtualKey.hitTop, virtualKey.hitBottom);
1875 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001876 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001877}
1878
Jeff Brown8d608662010-08-30 03:02:23 -07001879void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001880 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001881 Calibration& out = mCalibration;
1882
Jeff Brown511ee5f2010-10-18 13:32:20 -07001883 // Position
1884 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1885 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1886 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1887 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1888
Jeff Brownc6d282b2010-10-14 21:42:15 -07001889 // Touch Size
1890 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1891 String8 touchSizeCalibrationString;
1892 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1893 if (touchSizeCalibrationString == "none") {
1894 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1895 } else if (touchSizeCalibrationString == "geometric") {
1896 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1897 } else if (touchSizeCalibrationString == "pressure") {
1898 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1899 } else if (touchSizeCalibrationString != "default") {
1900 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1901 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001902 }
1903 }
1904
Jeff Brownc6d282b2010-10-14 21:42:15 -07001905 // Tool Size
1906 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1907 String8 toolSizeCalibrationString;
1908 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1909 if (toolSizeCalibrationString == "none") {
1910 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1911 } else if (toolSizeCalibrationString == "geometric") {
1912 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1913 } else if (toolSizeCalibrationString == "linear") {
1914 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1915 } else if (toolSizeCalibrationString == "area") {
1916 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1917 } else if (toolSizeCalibrationString != "default") {
1918 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1919 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001920 }
1921 }
1922
Jeff Brownc6d282b2010-10-14 21:42:15 -07001923 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1924 out.toolSizeLinearScale);
1925 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1926 out.toolSizeLinearBias);
1927 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1928 out.toolSizeAreaScale);
1929 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1930 out.toolSizeAreaBias);
1931 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1932 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07001933
1934 // Pressure
1935 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1936 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001937 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001938 if (pressureCalibrationString == "none") {
1939 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1940 } else if (pressureCalibrationString == "physical") {
1941 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1942 } else if (pressureCalibrationString == "amplitude") {
1943 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1944 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001945 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001946 pressureCalibrationString.string());
1947 }
1948 }
1949
1950 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1951 String8 pressureSourceString;
1952 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1953 if (pressureSourceString == "pressure") {
1954 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1955 } else if (pressureSourceString == "touch") {
1956 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1957 } else if (pressureSourceString != "default") {
1958 LOGW("Invalid value for touch.pressure.source: '%s'",
1959 pressureSourceString.string());
1960 }
1961 }
1962
1963 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1964 out.pressureScale);
1965
1966 // Size
1967 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1968 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001969 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001970 if (sizeCalibrationString == "none") {
1971 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1972 } else if (sizeCalibrationString == "normalized") {
1973 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1974 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001975 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001976 sizeCalibrationString.string());
1977 }
1978 }
1979
1980 // Orientation
1981 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1982 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001983 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001984 if (orientationCalibrationString == "none") {
1985 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1986 } else if (orientationCalibrationString == "interpolated") {
1987 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08001988 } else if (orientationCalibrationString == "vector") {
1989 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001990 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001991 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001992 orientationCalibrationString.string());
1993 }
1994 }
1995}
1996
1997void TouchInputMapper::resolveCalibration() {
1998 // Pressure
1999 switch (mCalibration.pressureSource) {
2000 case Calibration::PRESSURE_SOURCE_DEFAULT:
2001 if (mRawAxes.pressure.valid) {
2002 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2003 } else if (mRawAxes.touchMajor.valid) {
2004 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2005 }
2006 break;
2007
2008 case Calibration::PRESSURE_SOURCE_PRESSURE:
2009 if (! mRawAxes.pressure.valid) {
2010 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2011 "the pressure axis is not available.");
2012 }
2013 break;
2014
2015 case Calibration::PRESSURE_SOURCE_TOUCH:
2016 if (! mRawAxes.touchMajor.valid) {
2017 LOGW("Calibration property touch.pressure.source is 'touch' but "
2018 "the touchMajor axis is not available.");
2019 }
2020 break;
2021
2022 default:
2023 break;
2024 }
2025
2026 switch (mCalibration.pressureCalibration) {
2027 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2028 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2029 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2030 } else {
2031 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2032 }
2033 break;
2034
2035 default:
2036 break;
2037 }
2038
Jeff Brownc6d282b2010-10-14 21:42:15 -07002039 // Tool Size
2040 switch (mCalibration.toolSizeCalibration) {
2041 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002042 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002043 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002044 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002045 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002046 }
2047 break;
2048
2049 default:
2050 break;
2051 }
2052
Jeff Brownc6d282b2010-10-14 21:42:15 -07002053 // Touch Size
2054 switch (mCalibration.touchSizeCalibration) {
2055 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002056 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002057 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2058 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002059 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002060 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002061 }
2062 break;
2063
2064 default:
2065 break;
2066 }
2067
2068 // Size
2069 switch (mCalibration.sizeCalibration) {
2070 case Calibration::SIZE_CALIBRATION_DEFAULT:
2071 if (mRawAxes.toolMajor.valid) {
2072 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2073 } else {
2074 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2075 }
2076 break;
2077
2078 default:
2079 break;
2080 }
2081
2082 // Orientation
2083 switch (mCalibration.orientationCalibration) {
2084 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2085 if (mRawAxes.orientation.valid) {
2086 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2087 } else {
2088 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2089 }
2090 break;
2091
2092 default:
2093 break;
2094 }
2095}
2096
Jeff Brownef3d7e82010-09-30 14:33:04 -07002097void TouchInputMapper::dumpCalibration(String8& dump) {
2098 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002099
Jeff Brown511ee5f2010-10-18 13:32:20 -07002100 // Position
2101 if (mCalibration.haveXOrigin) {
2102 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2103 }
2104 if (mCalibration.haveYOrigin) {
2105 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2106 }
2107 if (mCalibration.haveXScale) {
2108 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2109 }
2110 if (mCalibration.haveYScale) {
2111 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2112 }
2113
Jeff Brownc6d282b2010-10-14 21:42:15 -07002114 // Touch Size
2115 switch (mCalibration.touchSizeCalibration) {
2116 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2117 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002118 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002119 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2120 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002121 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002122 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2123 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002124 break;
2125 default:
2126 assert(false);
2127 }
2128
Jeff Brownc6d282b2010-10-14 21:42:15 -07002129 // Tool Size
2130 switch (mCalibration.toolSizeCalibration) {
2131 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2132 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002133 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002134 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2135 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002136 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002137 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2138 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2139 break;
2140 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2141 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002142 break;
2143 default:
2144 assert(false);
2145 }
2146
Jeff Brownc6d282b2010-10-14 21:42:15 -07002147 if (mCalibration.haveToolSizeLinearScale) {
2148 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2149 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002150 }
2151
Jeff Brownc6d282b2010-10-14 21:42:15 -07002152 if (mCalibration.haveToolSizeLinearBias) {
2153 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2154 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002155 }
2156
Jeff Brownc6d282b2010-10-14 21:42:15 -07002157 if (mCalibration.haveToolSizeAreaScale) {
2158 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2159 mCalibration.toolSizeAreaScale);
2160 }
2161
2162 if (mCalibration.haveToolSizeAreaBias) {
2163 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2164 mCalibration.toolSizeAreaBias);
2165 }
2166
2167 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002168 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002169 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002170 }
2171
2172 // Pressure
2173 switch (mCalibration.pressureCalibration) {
2174 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002175 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002176 break;
2177 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002178 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002179 break;
2180 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002181 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002182 break;
2183 default:
2184 assert(false);
2185 }
2186
2187 switch (mCalibration.pressureSource) {
2188 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002189 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002190 break;
2191 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002192 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002193 break;
2194 case Calibration::PRESSURE_SOURCE_DEFAULT:
2195 break;
2196 default:
2197 assert(false);
2198 }
2199
2200 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002201 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2202 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002203 }
2204
2205 // Size
2206 switch (mCalibration.sizeCalibration) {
2207 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002208 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002209 break;
2210 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002211 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002212 break;
2213 default:
2214 assert(false);
2215 }
2216
2217 // Orientation
2218 switch (mCalibration.orientationCalibration) {
2219 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002220 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002221 break;
2222 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002223 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002224 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002225 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2226 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2227 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002228 default:
2229 assert(false);
2230 }
2231}
2232
Jeff Brown6d0fec22010-07-23 21:28:06 -07002233void TouchInputMapper::reset() {
2234 // Synthesize touch up event if touch is currently down.
2235 // This will also take care of finishing virtual key processing if needed.
2236 if (mLastTouch.pointerCount != 0) {
2237 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2238 mCurrentTouch.clear();
2239 syncTouch(when, true);
2240 }
2241
Jeff Brown6328cdc2010-07-29 18:18:33 -07002242 { // acquire lock
2243 AutoMutex _l(mLock);
2244 initializeLocked();
2245 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002246
Jeff Brown6328cdc2010-07-29 18:18:33 -07002247 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002248}
2249
2250void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002251 uint32_t policyFlags = 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002252
Jeff Brown6328cdc2010-07-29 18:18:33 -07002253 // Preprocess pointer data.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002254
Jeff Brown6d0fec22010-07-23 21:28:06 -07002255 if (mParameters.useBadTouchFilter) {
2256 if (applyBadTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002257 havePointerIds = false;
2258 }
2259 }
2260
Jeff Brown6d0fec22010-07-23 21:28:06 -07002261 if (mParameters.useJumpyTouchFilter) {
2262 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002263 havePointerIds = false;
2264 }
2265 }
2266
2267 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002268 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002269 }
2270
Jeff Brown6d0fec22010-07-23 21:28:06 -07002271 TouchData temp;
2272 TouchData* savedTouch;
2273 if (mParameters.useAveragingTouchFilter) {
2274 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002275 savedTouch = & temp;
2276
Jeff Brown6d0fec22010-07-23 21:28:06 -07002277 applyAveragingTouchFilter();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002278 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002279 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002280 }
2281
Jeff Brown6328cdc2010-07-29 18:18:33 -07002282 // Process touches and virtual keys.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002283
Jeff Brown6d0fec22010-07-23 21:28:06 -07002284 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2285 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002286 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002287 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002288 }
2289
Jeff Brown6328cdc2010-07-29 18:18:33 -07002290 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002291
Jeff Brown6d0fec22010-07-23 21:28:06 -07002292 if (touchResult == DROP_STROKE) {
2293 mLastTouch.clear();
2294 } else {
2295 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002296 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002297}
2298
Jeff Brown6d0fec22010-07-23 21:28:06 -07002299TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2300 nsecs_t when, uint32_t policyFlags) {
2301 int32_t keyEventAction, keyEventFlags;
2302 int32_t keyCode, scanCode, downTime;
2303 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002304
Jeff Brown6328cdc2010-07-29 18:18:33 -07002305 { // acquire lock
2306 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002307
Jeff Brown6328cdc2010-07-29 18:18:33 -07002308 // Update surface size and orientation, including virtual key positions.
2309 if (! configureSurfaceLocked()) {
2310 return DROP_STROKE;
2311 }
2312
2313 // Check for virtual key press.
2314 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002315 if (mCurrentTouch.pointerCount == 0) {
2316 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002317 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002318#if DEBUG_VIRTUAL_KEYS
2319 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002320 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002321#endif
2322 keyEventAction = AKEY_EVENT_ACTION_UP;
2323 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2324 touchResult = SKIP_TOUCH;
2325 goto DispatchVirtualKey;
2326 }
2327
2328 if (mCurrentTouch.pointerCount == 1) {
2329 int32_t x = mCurrentTouch.pointers[0].x;
2330 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002331 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2332 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002333 // Pointer is still within the space of the virtual key.
2334 return SKIP_TOUCH;
2335 }
2336 }
2337
2338 // Pointer left virtual key area or another pointer also went down.
2339 // Send key cancellation and drop the stroke so subsequent motions will be
2340 // considered fresh downs. This is useful when the user swipes away from the
2341 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002342 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002343#if DEBUG_VIRTUAL_KEYS
2344 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002345 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002346#endif
2347 keyEventAction = AKEY_EVENT_ACTION_UP;
2348 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2349 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002350
2351 // Check whether the pointer moved inside the display area where we should
2352 // start a new stroke.
2353 int32_t x = mCurrentTouch.pointers[0].x;
2354 int32_t y = mCurrentTouch.pointers[0].y;
2355 if (isPointInsideSurfaceLocked(x, y)) {
2356 mLastTouch.clear();
2357 touchResult = DISPATCH_TOUCH;
2358 } else {
2359 touchResult = DROP_STROKE;
2360 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002361 } else {
2362 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2363 // Pointer just went down. Handle off-screen touches, if needed.
2364 int32_t x = mCurrentTouch.pointers[0].x;
2365 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002366 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002367 // If exactly one pointer went down, check for virtual key hit.
2368 // Otherwise we will drop the entire stroke.
2369 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002370 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002371 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002372 if (mContext->shouldDropVirtualKey(when, getDevice(),
2373 virtualKey->keyCode, virtualKey->scanCode)) {
2374 return DROP_STROKE;
2375 }
2376
Jeff Brown6328cdc2010-07-29 18:18:33 -07002377 mLocked.currentVirtualKey.down = true;
2378 mLocked.currentVirtualKey.downTime = when;
2379 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2380 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002381#if DEBUG_VIRTUAL_KEYS
2382 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002383 mLocked.currentVirtualKey.keyCode,
2384 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002385#endif
2386 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2387 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2388 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2389 touchResult = SKIP_TOUCH;
2390 goto DispatchVirtualKey;
2391 }
2392 }
2393 return DROP_STROKE;
2394 }
2395 }
2396 return DISPATCH_TOUCH;
2397 }
2398
2399 DispatchVirtualKey:
2400 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002401 keyCode = mLocked.currentVirtualKey.keyCode;
2402 scanCode = mLocked.currentVirtualKey.scanCode;
2403 downTime = mLocked.currentVirtualKey.downTime;
2404 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002405
2406 // Dispatch virtual key.
2407 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002408 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002409 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2410 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2411 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002412}
2413
Jeff Brownfe508922011-01-18 15:10:10 -08002414void TouchInputMapper::detectGestures(nsecs_t when) {
2415 // Disable all virtual key touches that happen within a short time interval of the
2416 // most recent touch. The idea is to filter out stray virtual key presses when
2417 // interacting with the touch screen.
2418 //
2419 // Problems we're trying to solve:
2420 //
2421 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2422 // virtual key area that is implemented by a separate touch panel and accidentally
2423 // triggers a virtual key.
2424 //
2425 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2426 // area and accidentally triggers a virtual key. This often happens when virtual keys
2427 // are layed out below the screen near to where the on screen keyboard's space bar
2428 // is displayed.
2429 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2430 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2431 }
2432}
2433
Jeff Brown6d0fec22010-07-23 21:28:06 -07002434void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2435 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2436 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002437 if (currentPointerCount == 0 && lastPointerCount == 0) {
2438 return; // nothing to do!
2439 }
2440
Jeff Brown6d0fec22010-07-23 21:28:06 -07002441 BitSet32 currentIdBits = mCurrentTouch.idBits;
2442 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002443
2444 if (currentIdBits == lastIdBits) {
2445 // No pointer id changes so this is a move event.
2446 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002447 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002448 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002449 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002450 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002451 // There may be pointers going up and pointers going down and pointers moving
2452 // all at the same time.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002453 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2454 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2455 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002456 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002457
Jeff Brownc3db8582010-10-20 15:33:38 -07002458 // Produce an intermediate representation of the touch data that consists of the
2459 // old location of pointers that have just gone up and the new location of pointers that
2460 // have just moved but omits the location of pointers that have just gone down.
2461 TouchData interimTouch;
2462 interimTouch.copyFrom(mLastTouch);
2463
2464 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2465 bool moveNeeded = false;
2466 while (!moveIdBits.isEmpty()) {
2467 uint32_t moveId = moveIdBits.firstMarkedBit();
2468 moveIdBits.clearBit(moveId);
2469
2470 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2471 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2472 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2473 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2474 moveNeeded = true;
2475 }
2476 }
2477
2478 // Dispatch pointer up events using the interim pointer locations.
2479 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002480 uint32_t upId = upIdBits.firstMarkedBit();
2481 upIdBits.clearBit(upId);
2482 BitSet32 oldActiveIdBits = activeIdBits;
2483 activeIdBits.clearBit(upId);
2484
2485 int32_t motionEventAction;
2486 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002487 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002488 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002489 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002490 }
2491
Jeff Brownc3db8582010-10-20 15:33:38 -07002492 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002493 oldActiveIdBits, upId, pointerCount, motionEventAction);
2494 pointerCount -= 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002495 }
2496
Jeff Brownc3db8582010-10-20 15:33:38 -07002497 // Dispatch move events if any of the remaining pointers moved from their old locations.
2498 // Although applications receive new locations as part of individual pointer up
2499 // events, they do not generally handle them except when presented in a move event.
2500 if (moveNeeded) {
2501 dispatchTouch(when, policyFlags, &mCurrentTouch,
2502 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2503 }
2504
2505 // Dispatch pointer down events using the new pointer locations.
2506 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002507 uint32_t downId = downIdBits.firstMarkedBit();
2508 downIdBits.clearBit(downId);
2509 BitSet32 oldActiveIdBits = activeIdBits;
2510 activeIdBits.markBit(downId);
2511
2512 int32_t motionEventAction;
2513 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002514 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002515 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002516 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002517 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002518 }
2519
Jeff Brown8d608662010-08-30 03:02:23 -07002520 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002521 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002522 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002523 }
2524 }
2525}
2526
Jeff Brown6d0fec22010-07-23 21:28:06 -07002527void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002528 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002529 int32_t motionEventAction) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002530 int32_t pointerIds[MAX_POINTERS];
2531 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002532 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002533 float xPrecision, yPrecision;
2534
2535 { // acquire lock
2536 AutoMutex _l(mLock);
2537
2538 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2539 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002540 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002541 uint32_t id = idBits.firstMarkedBit();
2542 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002543 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002544
Jeff Brown8d608662010-08-30 03:02:23 -07002545 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002546
Jeff Brown8d608662010-08-30 03:02:23 -07002547 // X and Y
2548 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2549 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002550
Jeff Brown8d608662010-08-30 03:02:23 -07002551 // ToolMajor and ToolMinor
2552 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002553 switch (mCalibration.toolSizeCalibration) {
2554 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002555 toolMajor = in.toolMajor * mLocked.geometricScale;
2556 if (mRawAxes.toolMinor.valid) {
2557 toolMinor = in.toolMinor * mLocked.geometricScale;
2558 } else {
2559 toolMinor = toolMajor;
2560 }
2561 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002562 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002563 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002564 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002565 : 0;
2566 if (mRawAxes.toolMinor.valid) {
2567 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002568 ? in.toolMinor * mLocked.toolSizeLinearScale
2569 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002570 : 0;
2571 } else {
2572 toolMinor = toolMajor;
2573 }
2574 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002575 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2576 if (in.toolMajor != 0) {
2577 float diameter = sqrtf(in.toolMajor
2578 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2579 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2580 } else {
2581 toolMajor = 0;
2582 }
2583 toolMinor = toolMajor;
2584 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002585 default:
2586 toolMajor = 0;
2587 toolMinor = 0;
2588 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002589 }
2590
Jeff Brownc6d282b2010-10-14 21:42:15 -07002591 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002592 toolMajor /= pointerCount;
2593 toolMinor /= pointerCount;
2594 }
2595
2596 // Pressure
2597 float rawPressure;
2598 switch (mCalibration.pressureSource) {
2599 case Calibration::PRESSURE_SOURCE_PRESSURE:
2600 rawPressure = in.pressure;
2601 break;
2602 case Calibration::PRESSURE_SOURCE_TOUCH:
2603 rawPressure = in.touchMajor;
2604 break;
2605 default:
2606 rawPressure = 0;
2607 }
2608
2609 float pressure;
2610 switch (mCalibration.pressureCalibration) {
2611 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2612 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2613 pressure = rawPressure * mLocked.pressureScale;
2614 break;
2615 default:
2616 pressure = 1;
2617 break;
2618 }
2619
2620 // TouchMajor and TouchMinor
2621 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002622 switch (mCalibration.touchSizeCalibration) {
2623 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002624 touchMajor = in.touchMajor * mLocked.geometricScale;
2625 if (mRawAxes.touchMinor.valid) {
2626 touchMinor = in.touchMinor * mLocked.geometricScale;
2627 } else {
2628 touchMinor = touchMajor;
2629 }
2630 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002631 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002632 touchMajor = toolMajor * pressure;
2633 touchMinor = toolMinor * pressure;
2634 break;
2635 default:
2636 touchMajor = 0;
2637 touchMinor = 0;
2638 break;
2639 }
2640
2641 if (touchMajor > toolMajor) {
2642 touchMajor = toolMajor;
2643 }
2644 if (touchMinor > toolMinor) {
2645 touchMinor = toolMinor;
2646 }
2647
2648 // Size
2649 float size;
2650 switch (mCalibration.sizeCalibration) {
2651 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2652 float rawSize = mRawAxes.toolMinor.valid
2653 ? avg(in.toolMajor, in.toolMinor)
2654 : in.toolMajor;
2655 size = rawSize * mLocked.sizeScale;
2656 break;
2657 }
2658 default:
2659 size = 0;
2660 break;
2661 }
2662
2663 // Orientation
2664 float orientation;
2665 switch (mCalibration.orientationCalibration) {
2666 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2667 orientation = in.orientation * mLocked.orientationScale;
2668 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002669 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2670 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2671 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2672 if (c1 != 0 || c2 != 0) {
2673 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002674 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2675 touchMajor *= scale;
2676 touchMinor /= scale;
2677 toolMajor *= scale;
2678 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002679 } else {
2680 orientation = 0;
2681 }
2682 break;
2683 }
Jeff Brown8d608662010-08-30 03:02:23 -07002684 default:
2685 orientation = 0;
2686 }
2687
2688 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002689 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002690 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002691 float xTemp = x;
2692 x = y;
2693 y = mLocked.surfaceWidth - xTemp;
2694 orientation -= M_PI_2;
2695 if (orientation < - M_PI_2) {
2696 orientation += M_PI;
2697 }
2698 break;
2699 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002700 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002701 x = mLocked.surfaceWidth - x;
2702 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002703 break;
2704 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002705 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002706 float xTemp = x;
2707 x = mLocked.surfaceHeight - y;
2708 y = xTemp;
2709 orientation += M_PI_2;
2710 if (orientation > M_PI_2) {
2711 orientation -= M_PI;
2712 }
2713 break;
2714 }
2715 }
2716
Jeff Brown8d608662010-08-30 03:02:23 -07002717 // Write output coords.
2718 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002719 out.clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -08002720 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2721 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2722 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2723 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2724 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2725 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2726 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2727 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2728 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002729
Jeff Brown8d608662010-08-30 03:02:23 -07002730 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002731
2732 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002733 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002734 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002735 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002736
2737 // Check edge flags by looking only at the first pointer since the flags are
2738 // global to the event.
2739 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownebbd5d12011-02-17 13:01:34 -08002740 float x = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
2741 float y = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08002742
2743 if (x <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002744 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002745 } else if (x >= mLocked.orientedSurfaceWidth) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002746 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2747 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08002748 if (y <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002749 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002750 } else if (y >= mLocked.orientedSurfaceHeight) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002751 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2752 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002753 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002754
2755 xPrecision = mLocked.orientedXPrecision;
2756 yPrecision = mLocked.orientedYPrecision;
2757 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002758
Jeff Brown83c09682010-12-23 17:50:18 -08002759 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002760 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002761 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002762 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002763}
2764
Jeff Brown6328cdc2010-07-29 18:18:33 -07002765bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002766 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2767 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2768 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002769 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002770 return true;
2771}
2772
Jeff Brown6328cdc2010-07-29 18:18:33 -07002773const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2774 int32_t x, int32_t y) {
2775 size_t numVirtualKeys = mLocked.virtualKeys.size();
2776 for (size_t i = 0; i < numVirtualKeys; i++) {
2777 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002778
2779#if DEBUG_VIRTUAL_KEYS
2780 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2781 "left=%d, top=%d, right=%d, bottom=%d",
2782 x, y,
2783 virtualKey.keyCode, virtualKey.scanCode,
2784 virtualKey.hitLeft, virtualKey.hitTop,
2785 virtualKey.hitRight, virtualKey.hitBottom);
2786#endif
2787
2788 if (virtualKey.isHit(x, y)) {
2789 return & virtualKey;
2790 }
2791 }
2792
2793 return NULL;
2794}
2795
2796void TouchInputMapper::calculatePointerIds() {
2797 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2798 uint32_t lastPointerCount = mLastTouch.pointerCount;
2799
2800 if (currentPointerCount == 0) {
2801 // No pointers to assign.
2802 mCurrentTouch.idBits.clear();
2803 } else if (lastPointerCount == 0) {
2804 // All pointers are new.
2805 mCurrentTouch.idBits.clear();
2806 for (uint32_t i = 0; i < currentPointerCount; i++) {
2807 mCurrentTouch.pointers[i].id = i;
2808 mCurrentTouch.idToIndex[i] = i;
2809 mCurrentTouch.idBits.markBit(i);
2810 }
2811 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2812 // Only one pointer and no change in count so it must have the same id as before.
2813 uint32_t id = mLastTouch.pointers[0].id;
2814 mCurrentTouch.pointers[0].id = id;
2815 mCurrentTouch.idToIndex[id] = 0;
2816 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2817 } else {
2818 // General case.
2819 // We build a heap of squared euclidean distances between current and last pointers
2820 // associated with the current and last pointer indices. Then, we find the best
2821 // match (by distance) for each current pointer.
2822 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2823
2824 uint32_t heapSize = 0;
2825 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2826 currentPointerIndex++) {
2827 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2828 lastPointerIndex++) {
2829 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2830 - mLastTouch.pointers[lastPointerIndex].x;
2831 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2832 - mLastTouch.pointers[lastPointerIndex].y;
2833
2834 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2835
2836 // Insert new element into the heap (sift up).
2837 heap[heapSize].currentPointerIndex = currentPointerIndex;
2838 heap[heapSize].lastPointerIndex = lastPointerIndex;
2839 heap[heapSize].distance = distance;
2840 heapSize += 1;
2841 }
2842 }
2843
2844 // Heapify
2845 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2846 startIndex -= 1;
2847 for (uint32_t parentIndex = startIndex; ;) {
2848 uint32_t childIndex = parentIndex * 2 + 1;
2849 if (childIndex >= heapSize) {
2850 break;
2851 }
2852
2853 if (childIndex + 1 < heapSize
2854 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2855 childIndex += 1;
2856 }
2857
2858 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2859 break;
2860 }
2861
2862 swap(heap[parentIndex], heap[childIndex]);
2863 parentIndex = childIndex;
2864 }
2865 }
2866
2867#if DEBUG_POINTER_ASSIGNMENT
2868 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2869 for (size_t i = 0; i < heapSize; i++) {
2870 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2871 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2872 heap[i].distance);
2873 }
2874#endif
2875
2876 // Pull matches out by increasing order of distance.
2877 // To avoid reassigning pointers that have already been matched, the loop keeps track
2878 // of which last and current pointers have been matched using the matchedXXXBits variables.
2879 // It also tracks the used pointer id bits.
2880 BitSet32 matchedLastBits(0);
2881 BitSet32 matchedCurrentBits(0);
2882 BitSet32 usedIdBits(0);
2883 bool first = true;
2884 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2885 for (;;) {
2886 if (first) {
2887 // The first time through the loop, we just consume the root element of
2888 // the heap (the one with smallest distance).
2889 first = false;
2890 } else {
2891 // Previous iterations consumed the root element of the heap.
2892 // Pop root element off of the heap (sift down).
2893 heapSize -= 1;
2894 assert(heapSize > 0);
2895
2896 // Sift down.
2897 heap[0] = heap[heapSize];
2898 for (uint32_t parentIndex = 0; ;) {
2899 uint32_t childIndex = parentIndex * 2 + 1;
2900 if (childIndex >= heapSize) {
2901 break;
2902 }
2903
2904 if (childIndex + 1 < heapSize
2905 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2906 childIndex += 1;
2907 }
2908
2909 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2910 break;
2911 }
2912
2913 swap(heap[parentIndex], heap[childIndex]);
2914 parentIndex = childIndex;
2915 }
2916
2917#if DEBUG_POINTER_ASSIGNMENT
2918 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2919 for (size_t i = 0; i < heapSize; i++) {
2920 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2921 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2922 heap[i].distance);
2923 }
2924#endif
2925 }
2926
2927 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2928 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2929
2930 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2931 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2932
2933 matchedCurrentBits.markBit(currentPointerIndex);
2934 matchedLastBits.markBit(lastPointerIndex);
2935
2936 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2937 mCurrentTouch.pointers[currentPointerIndex].id = id;
2938 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2939 usedIdBits.markBit(id);
2940
2941#if DEBUG_POINTER_ASSIGNMENT
2942 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2943 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2944#endif
2945 break;
2946 }
2947 }
2948
2949 // Assign fresh ids to new pointers.
2950 if (currentPointerCount > lastPointerCount) {
2951 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2952 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2953 uint32_t id = usedIdBits.firstUnmarkedBit();
2954
2955 mCurrentTouch.pointers[currentPointerIndex].id = id;
2956 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2957 usedIdBits.markBit(id);
2958
2959#if DEBUG_POINTER_ASSIGNMENT
2960 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2961 currentPointerIndex, id);
2962#endif
2963
2964 if (--i == 0) break; // done
2965 matchedCurrentBits.markBit(currentPointerIndex);
2966 }
2967 }
2968
2969 // Fix id bits.
2970 mCurrentTouch.idBits = usedIdBits;
2971 }
2972}
2973
2974/* Special hack for devices that have bad screen data: if one of the
2975 * points has moved more than a screen height from the last position,
2976 * then drop it. */
2977bool TouchInputMapper::applyBadTouchFilter() {
2978 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002979 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002980 return false;
2981 }
2982
2983 uint32_t pointerCount = mCurrentTouch.pointerCount;
2984
2985 // Nothing to do if there are no points.
2986 if (pointerCount == 0) {
2987 return false;
2988 }
2989
2990 // Don't do anything if a finger is going down or up. We run
2991 // here before assigning pointer IDs, so there isn't a good
2992 // way to do per-finger matching.
2993 if (pointerCount != mLastTouch.pointerCount) {
2994 return false;
2995 }
2996
2997 // We consider a single movement across more than a 7/16 of
2998 // the long size of the screen to be bad. This was a magic value
2999 // determined by looking at the maximum distance it is feasible
3000 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07003001 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003002
3003 // XXX The original code in InputDevice.java included commented out
3004 // code for testing the X axis. Note that when we drop a point
3005 // we don't actually restore the old X either. Strange.
3006 // The old code also tries to track when bad points were previously
3007 // detected but it turns out that due to the placement of a "break"
3008 // at the end of the loop, we never set mDroppedBadPoint to true
3009 // so it is effectively dead code.
3010 // Need to figure out if the old code is busted or just overcomplicated
3011 // but working as intended.
3012
3013 // Look through all new points and see if any are farther than
3014 // acceptable from all previous points.
3015 for (uint32_t i = pointerCount; i-- > 0; ) {
3016 int32_t y = mCurrentTouch.pointers[i].y;
3017 int32_t closestY = INT_MAX;
3018 int32_t closestDeltaY = 0;
3019
3020#if DEBUG_HACKS
3021 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3022#endif
3023
3024 for (uint32_t j = pointerCount; j-- > 0; ) {
3025 int32_t lastY = mLastTouch.pointers[j].y;
3026 int32_t deltaY = abs(y - lastY);
3027
3028#if DEBUG_HACKS
3029 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3030 j, lastY, deltaY);
3031#endif
3032
3033 if (deltaY < maxDeltaY) {
3034 goto SkipSufficientlyClosePoint;
3035 }
3036 if (deltaY < closestDeltaY) {
3037 closestDeltaY = deltaY;
3038 closestY = lastY;
3039 }
3040 }
3041
3042 // Must not have found a close enough match.
3043#if DEBUG_HACKS
3044 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3045 i, y, closestY, closestDeltaY, maxDeltaY);
3046#endif
3047
3048 mCurrentTouch.pointers[i].y = closestY;
3049 return true; // XXX original code only corrects one point
3050
3051 SkipSufficientlyClosePoint: ;
3052 }
3053
3054 // No change.
3055 return false;
3056}
3057
3058/* Special hack for devices that have bad screen data: drop points where
3059 * the coordinate value for one axis has jumped to the other pointer's location.
3060 */
3061bool TouchInputMapper::applyJumpyTouchFilter() {
3062 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003063 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003064 return false;
3065 }
3066
3067 uint32_t pointerCount = mCurrentTouch.pointerCount;
3068 if (mLastTouch.pointerCount != pointerCount) {
3069#if DEBUG_HACKS
3070 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3071 mLastTouch.pointerCount, pointerCount);
3072 for (uint32_t i = 0; i < pointerCount; i++) {
3073 LOGD(" Pointer %d (%d, %d)", i,
3074 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3075 }
3076#endif
3077
3078 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3079 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3080 // Just drop the first few events going from 1 to 2 pointers.
3081 // They're bad often enough that they're not worth considering.
3082 mCurrentTouch.pointerCount = 1;
3083 mJumpyTouchFilter.jumpyPointsDropped += 1;
3084
3085#if DEBUG_HACKS
3086 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3087#endif
3088 return true;
3089 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3090 // The event when we go from 2 -> 1 tends to be messed up too
3091 mCurrentTouch.pointerCount = 2;
3092 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3093 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3094 mJumpyTouchFilter.jumpyPointsDropped += 1;
3095
3096#if DEBUG_HACKS
3097 for (int32_t i = 0; i < 2; i++) {
3098 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3099 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3100 }
3101#endif
3102 return true;
3103 }
3104 }
3105 // Reset jumpy points dropped on other transitions or if limit exceeded.
3106 mJumpyTouchFilter.jumpyPointsDropped = 0;
3107
3108#if DEBUG_HACKS
3109 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3110#endif
3111 return false;
3112 }
3113
3114 // We have the same number of pointers as last time.
3115 // A 'jumpy' point is one where the coordinate value for one axis
3116 // has jumped to the other pointer's location. No need to do anything
3117 // else if we only have one pointer.
3118 if (pointerCount < 2) {
3119 return false;
3120 }
3121
3122 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003123 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003124
3125 // We only replace the single worst jumpy point as characterized by pointer distance
3126 // in a single axis.
3127 int32_t badPointerIndex = -1;
3128 int32_t badPointerReplacementIndex = -1;
3129 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3130
3131 for (uint32_t i = pointerCount; i-- > 0; ) {
3132 int32_t x = mCurrentTouch.pointers[i].x;
3133 int32_t y = mCurrentTouch.pointers[i].y;
3134
3135#if DEBUG_HACKS
3136 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3137#endif
3138
3139 // Check if a touch point is too close to another's coordinates
3140 bool dropX = false, dropY = false;
3141 for (uint32_t j = 0; j < pointerCount; j++) {
3142 if (i == j) {
3143 continue;
3144 }
3145
3146 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3147 dropX = true;
3148 break;
3149 }
3150
3151 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3152 dropY = true;
3153 break;
3154 }
3155 }
3156 if (! dropX && ! dropY) {
3157 continue; // not jumpy
3158 }
3159
3160 // Find a replacement candidate by comparing with older points on the
3161 // complementary (non-jumpy) axis.
3162 int32_t distance = INT_MIN; // distance to be corrected
3163 int32_t replacementIndex = -1;
3164
3165 if (dropX) {
3166 // X looks too close. Find an older replacement point with a close Y.
3167 int32_t smallestDeltaY = INT_MAX;
3168 for (uint32_t j = 0; j < pointerCount; j++) {
3169 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3170 if (deltaY < smallestDeltaY) {
3171 smallestDeltaY = deltaY;
3172 replacementIndex = j;
3173 }
3174 }
3175 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3176 } else {
3177 // Y looks too close. Find an older replacement point with a close X.
3178 int32_t smallestDeltaX = INT_MAX;
3179 for (uint32_t j = 0; j < pointerCount; j++) {
3180 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3181 if (deltaX < smallestDeltaX) {
3182 smallestDeltaX = deltaX;
3183 replacementIndex = j;
3184 }
3185 }
3186 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3187 }
3188
3189 // If replacing this pointer would correct a worse error than the previous ones
3190 // considered, then use this replacement instead.
3191 if (distance > badPointerDistance) {
3192 badPointerIndex = i;
3193 badPointerReplacementIndex = replacementIndex;
3194 badPointerDistance = distance;
3195 }
3196 }
3197
3198 // Correct the jumpy pointer if one was found.
3199 if (badPointerIndex >= 0) {
3200#if DEBUG_HACKS
3201 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3202 badPointerIndex,
3203 mLastTouch.pointers[badPointerReplacementIndex].x,
3204 mLastTouch.pointers[badPointerReplacementIndex].y);
3205#endif
3206
3207 mCurrentTouch.pointers[badPointerIndex].x =
3208 mLastTouch.pointers[badPointerReplacementIndex].x;
3209 mCurrentTouch.pointers[badPointerIndex].y =
3210 mLastTouch.pointers[badPointerReplacementIndex].y;
3211 mJumpyTouchFilter.jumpyPointsDropped += 1;
3212 return true;
3213 }
3214 }
3215
3216 mJumpyTouchFilter.jumpyPointsDropped = 0;
3217 return false;
3218}
3219
3220/* Special hack for devices that have bad screen data: aggregate and
3221 * compute averages of the coordinate data, to reduce the amount of
3222 * jitter seen by applications. */
3223void TouchInputMapper::applyAveragingTouchFilter() {
3224 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3225 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3226 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3227 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003228 int32_t pressure;
3229 switch (mCalibration.pressureSource) {
3230 case Calibration::PRESSURE_SOURCE_PRESSURE:
3231 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3232 break;
3233 case Calibration::PRESSURE_SOURCE_TOUCH:
3234 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3235 break;
3236 default:
3237 pressure = 1;
3238 break;
3239 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003240
3241 if (mLastTouch.idBits.hasBit(id)) {
3242 // Pointer was down before and is still down now.
3243 // Compute average over history trace.
3244 uint32_t start = mAveragingTouchFilter.historyStart[id];
3245 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3246
3247 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3248 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3249 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3250
3251#if DEBUG_HACKS
3252 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3253 id, distance);
3254#endif
3255
3256 if (distance < AVERAGING_DISTANCE_LIMIT) {
3257 // Increment end index in preparation for recording new historical data.
3258 end += 1;
3259 if (end > AVERAGING_HISTORY_SIZE) {
3260 end = 0;
3261 }
3262
3263 // If the end index has looped back to the start index then we have filled
3264 // the historical trace up to the desired size so we drop the historical
3265 // data at the start of the trace.
3266 if (end == start) {
3267 start += 1;
3268 if (start > AVERAGING_HISTORY_SIZE) {
3269 start = 0;
3270 }
3271 }
3272
3273 // Add the raw data to the historical trace.
3274 mAveragingTouchFilter.historyStart[id] = start;
3275 mAveragingTouchFilter.historyEnd[id] = end;
3276 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3277 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3278 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3279
3280 // Average over all historical positions in the trace by total pressure.
3281 int32_t averagedX = 0;
3282 int32_t averagedY = 0;
3283 int32_t totalPressure = 0;
3284 for (;;) {
3285 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3286 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3287 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3288 .pointers[id].pressure;
3289
3290 averagedX += historicalX * historicalPressure;
3291 averagedY += historicalY * historicalPressure;
3292 totalPressure += historicalPressure;
3293
3294 if (start == end) {
3295 break;
3296 }
3297
3298 start += 1;
3299 if (start > AVERAGING_HISTORY_SIZE) {
3300 start = 0;
3301 }
3302 }
3303
Jeff Brown8d608662010-08-30 03:02:23 -07003304 if (totalPressure != 0) {
3305 averagedX /= totalPressure;
3306 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003307
3308#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003309 LOGD("AveragingTouchFilter: Pointer id %d - "
3310 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3311 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003312#endif
3313
Jeff Brown8d608662010-08-30 03:02:23 -07003314 mCurrentTouch.pointers[currentIndex].x = averagedX;
3315 mCurrentTouch.pointers[currentIndex].y = averagedY;
3316 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003317 } else {
3318#if DEBUG_HACKS
3319 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3320#endif
3321 }
3322 } else {
3323#if DEBUG_HACKS
3324 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3325#endif
3326 }
3327
3328 // Reset pointer history.
3329 mAveragingTouchFilter.historyStart[id] = 0;
3330 mAveragingTouchFilter.historyEnd[id] = 0;
3331 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3332 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3333 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3334 }
3335}
3336
3337int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003338 { // acquire lock
3339 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003340
Jeff Brown6328cdc2010-07-29 18:18:33 -07003341 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003342 return AKEY_STATE_VIRTUAL;
3343 }
3344
Jeff Brown6328cdc2010-07-29 18:18:33 -07003345 size_t numVirtualKeys = mLocked.virtualKeys.size();
3346 for (size_t i = 0; i < numVirtualKeys; i++) {
3347 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003348 if (virtualKey.keyCode == keyCode) {
3349 return AKEY_STATE_UP;
3350 }
3351 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003352 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003353
3354 return AKEY_STATE_UNKNOWN;
3355}
3356
3357int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003358 { // acquire lock
3359 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003360
Jeff Brown6328cdc2010-07-29 18:18:33 -07003361 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003362 return AKEY_STATE_VIRTUAL;
3363 }
3364
Jeff Brown6328cdc2010-07-29 18:18:33 -07003365 size_t numVirtualKeys = mLocked.virtualKeys.size();
3366 for (size_t i = 0; i < numVirtualKeys; i++) {
3367 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003368 if (virtualKey.scanCode == scanCode) {
3369 return AKEY_STATE_UP;
3370 }
3371 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003372 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003373
3374 return AKEY_STATE_UNKNOWN;
3375}
3376
3377bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3378 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003379 { // acquire lock
3380 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003381
Jeff Brown6328cdc2010-07-29 18:18:33 -07003382 size_t numVirtualKeys = mLocked.virtualKeys.size();
3383 for (size_t i = 0; i < numVirtualKeys; i++) {
3384 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003385
3386 for (size_t i = 0; i < numCodes; i++) {
3387 if (virtualKey.keyCode == keyCodes[i]) {
3388 outFlags[i] = 1;
3389 }
3390 }
3391 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003392 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003393
3394 return true;
3395}
3396
3397
3398// --- SingleTouchInputMapper ---
3399
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003400SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3401 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003402 initialize();
3403}
3404
3405SingleTouchInputMapper::~SingleTouchInputMapper() {
3406}
3407
3408void SingleTouchInputMapper::initialize() {
3409 mAccumulator.clear();
3410
3411 mDown = false;
3412 mX = 0;
3413 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003414 mPressure = 0; // default to 0 for devices that don't report pressure
3415 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003416}
3417
3418void SingleTouchInputMapper::reset() {
3419 TouchInputMapper::reset();
3420
Jeff Brown6d0fec22010-07-23 21:28:06 -07003421 initialize();
3422 }
3423
3424void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3425 switch (rawEvent->type) {
3426 case EV_KEY:
3427 switch (rawEvent->scanCode) {
3428 case BTN_TOUCH:
3429 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3430 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003431 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3432 // not have received valid position information yet. This logic assumes that
3433 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003434 break;
3435 }
3436 break;
3437
3438 case EV_ABS:
3439 switch (rawEvent->scanCode) {
3440 case ABS_X:
3441 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3442 mAccumulator.absX = rawEvent->value;
3443 break;
3444 case ABS_Y:
3445 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3446 mAccumulator.absY = rawEvent->value;
3447 break;
3448 case ABS_PRESSURE:
3449 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3450 mAccumulator.absPressure = rawEvent->value;
3451 break;
3452 case ABS_TOOL_WIDTH:
3453 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3454 mAccumulator.absToolWidth = rawEvent->value;
3455 break;
3456 }
3457 break;
3458
3459 case EV_SYN:
3460 switch (rawEvent->scanCode) {
3461 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003462 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003463 break;
3464 }
3465 break;
3466 }
3467}
3468
3469void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003470 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003471 if (fields == 0) {
3472 return; // no new state changes, so nothing to do
3473 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003474
3475 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3476 mDown = mAccumulator.btnTouch;
3477 }
3478
3479 if (fields & Accumulator::FIELD_ABS_X) {
3480 mX = mAccumulator.absX;
3481 }
3482
3483 if (fields & Accumulator::FIELD_ABS_Y) {
3484 mY = mAccumulator.absY;
3485 }
3486
3487 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3488 mPressure = mAccumulator.absPressure;
3489 }
3490
3491 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003492 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003493 }
3494
3495 mCurrentTouch.clear();
3496
3497 if (mDown) {
3498 mCurrentTouch.pointerCount = 1;
3499 mCurrentTouch.pointers[0].id = 0;
3500 mCurrentTouch.pointers[0].x = mX;
3501 mCurrentTouch.pointers[0].y = mY;
3502 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003503 mCurrentTouch.pointers[0].touchMajor = 0;
3504 mCurrentTouch.pointers[0].touchMinor = 0;
3505 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3506 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003507 mCurrentTouch.pointers[0].orientation = 0;
3508 mCurrentTouch.idToIndex[0] = 0;
3509 mCurrentTouch.idBits.markBit(0);
3510 }
3511
3512 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003513
3514 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003515}
3516
Jeff Brown8d608662010-08-30 03:02:23 -07003517void SingleTouchInputMapper::configureRawAxes() {
3518 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003519
Jeff Brown8d608662010-08-30 03:02:23 -07003520 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3521 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3522 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3523 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003524}
3525
3526
3527// --- MultiTouchInputMapper ---
3528
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003529MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3530 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003531 initialize();
3532}
3533
3534MultiTouchInputMapper::~MultiTouchInputMapper() {
3535}
3536
3537void MultiTouchInputMapper::initialize() {
3538 mAccumulator.clear();
3539}
3540
3541void MultiTouchInputMapper::reset() {
3542 TouchInputMapper::reset();
3543
Jeff Brown6d0fec22010-07-23 21:28:06 -07003544 initialize();
3545}
3546
3547void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3548 switch (rawEvent->type) {
3549 case EV_ABS: {
3550 uint32_t pointerIndex = mAccumulator.pointerCount;
3551 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3552
3553 switch (rawEvent->scanCode) {
3554 case ABS_MT_POSITION_X:
3555 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3556 pointer->absMTPositionX = rawEvent->value;
3557 break;
3558 case ABS_MT_POSITION_Y:
3559 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3560 pointer->absMTPositionY = rawEvent->value;
3561 break;
3562 case ABS_MT_TOUCH_MAJOR:
3563 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3564 pointer->absMTTouchMajor = rawEvent->value;
3565 break;
3566 case ABS_MT_TOUCH_MINOR:
3567 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3568 pointer->absMTTouchMinor = rawEvent->value;
3569 break;
3570 case ABS_MT_WIDTH_MAJOR:
3571 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3572 pointer->absMTWidthMajor = rawEvent->value;
3573 break;
3574 case ABS_MT_WIDTH_MINOR:
3575 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3576 pointer->absMTWidthMinor = rawEvent->value;
3577 break;
3578 case ABS_MT_ORIENTATION:
3579 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3580 pointer->absMTOrientation = rawEvent->value;
3581 break;
3582 case ABS_MT_TRACKING_ID:
3583 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3584 pointer->absMTTrackingId = rawEvent->value;
3585 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003586 case ABS_MT_PRESSURE:
3587 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3588 pointer->absMTPressure = rawEvent->value;
3589 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003590 }
3591 break;
3592 }
3593
3594 case EV_SYN:
3595 switch (rawEvent->scanCode) {
3596 case SYN_MT_REPORT: {
3597 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3598 uint32_t pointerIndex = mAccumulator.pointerCount;
3599
3600 if (mAccumulator.pointers[pointerIndex].fields) {
3601 if (pointerIndex == MAX_POINTERS) {
3602 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3603 MAX_POINTERS);
3604 } else {
3605 pointerIndex += 1;
3606 mAccumulator.pointerCount = pointerIndex;
3607 }
3608 }
3609
3610 mAccumulator.pointers[pointerIndex].clear();
3611 break;
3612 }
3613
3614 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003615 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003616 break;
3617 }
3618 break;
3619 }
3620}
3621
3622void MultiTouchInputMapper::sync(nsecs_t when) {
3623 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003624 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003625
Jeff Brown6d0fec22010-07-23 21:28:06 -07003626 uint32_t inCount = mAccumulator.pointerCount;
3627 uint32_t outCount = 0;
3628 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003629
Jeff Brown6d0fec22010-07-23 21:28:06 -07003630 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003631
Jeff Brown6d0fec22010-07-23 21:28:06 -07003632 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003633 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3634 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003635
Jeff Brown6d0fec22010-07-23 21:28:06 -07003636 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003637 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3638 // Drop this finger.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003639 continue;
3640 }
3641
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003642 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3643 outPointer.x = inPointer.absMTPositionX;
3644 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003645
Jeff Brown8d608662010-08-30 03:02:23 -07003646 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3647 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003648 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3649 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003650 continue;
3651 }
Jeff Brown8d608662010-08-30 03:02:23 -07003652 outPointer.pressure = inPointer.absMTPressure;
3653 } else {
3654 // Default pressure to 0 if absent.
3655 outPointer.pressure = 0;
3656 }
3657
3658 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3659 if (inPointer.absMTTouchMajor <= 0) {
3660 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3661 // a pointer going up. Drop this finger.
3662 continue;
3663 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003664 outPointer.touchMajor = inPointer.absMTTouchMajor;
3665 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003666 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003667 outPointer.touchMajor = 0;
3668 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003669
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003670 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3671 outPointer.touchMinor = inPointer.absMTTouchMinor;
3672 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003673 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003674 outPointer.touchMinor = outPointer.touchMajor;
3675 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003676
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003677 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3678 outPointer.toolMajor = inPointer.absMTWidthMajor;
3679 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003680 // Default tool area to 0 if absent.
3681 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003682 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003683
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003684 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3685 outPointer.toolMinor = inPointer.absMTWidthMinor;
3686 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003687 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003688 outPointer.toolMinor = outPointer.toolMajor;
3689 }
3690
3691 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3692 outPointer.orientation = inPointer.absMTOrientation;
3693 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003694 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003695 outPointer.orientation = 0;
3696 }
3697
Jeff Brown8d608662010-08-30 03:02:23 -07003698 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003699 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003700 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3701 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003702
Jeff Brown6d0fec22010-07-23 21:28:06 -07003703 if (id > MAX_POINTER_ID) {
3704#if DEBUG_POINTERS
3705 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003706 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003707 id, MAX_POINTER_ID);
3708#endif
3709 havePointerIds = false;
3710 }
3711 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003712 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003713 mCurrentTouch.idToIndex[id] = outCount;
3714 mCurrentTouch.idBits.markBit(id);
3715 }
3716 } else {
3717 havePointerIds = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003718 }
3719 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003720
Jeff Brown6d0fec22010-07-23 21:28:06 -07003721 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003722 }
3723
Jeff Brown6d0fec22010-07-23 21:28:06 -07003724 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003725
Jeff Brown6d0fec22010-07-23 21:28:06 -07003726 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003727
3728 mAccumulator.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003729}
3730
Jeff Brown8d608662010-08-30 03:02:23 -07003731void MultiTouchInputMapper::configureRawAxes() {
3732 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003733
Jeff Brown8d608662010-08-30 03:02:23 -07003734 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3735 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3736 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3737 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3738 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3739 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3740 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3741 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003742}
3743
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003744
Jeff Browncb1404e2011-01-15 18:14:15 -08003745// --- JoystickInputMapper ---
3746
3747JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3748 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08003749}
3750
3751JoystickInputMapper::~JoystickInputMapper() {
3752}
3753
3754uint32_t JoystickInputMapper::getSources() {
3755 return AINPUT_SOURCE_JOYSTICK;
3756}
3757
3758void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3759 InputMapper::populateDeviceInfo(info);
3760
Jeff Brown6f2fba42011-02-19 01:08:02 -08003761 for (size_t i = 0; i < mAxes.size(); i++) {
3762 const Axis& axis = mAxes.valueAt(i);
3763 info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003764 }
3765}
3766
3767void JoystickInputMapper::dump(String8& dump) {
3768 dump.append(INDENT2 "Joystick Input Mapper:\n");
3769
Jeff Brown6f2fba42011-02-19 01:08:02 -08003770 dump.append(INDENT3 "Axes:\n");
3771 size_t numAxes = mAxes.size();
3772 for (size_t i = 0; i < numAxes; i++) {
3773 const Axis& axis = mAxes.valueAt(i);
3774 const char* label = getAxisLabel(axis.axis);
3775 char name[32];
3776 if (label) {
3777 strncpy(name, label, sizeof(name));
3778 name[sizeof(name) - 1] = '\0';
3779 } else {
3780 snprintf(name, sizeof(name), "%d", axis.axis);
3781 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003782 dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
Jeff Brown6f2fba42011-02-19 01:08:02 -08003783 "scale=%0.3f, offset=%0.3f\n",
Jeff Browncb1404e2011-01-15 18:14:15 -08003784 name, axis.min, axis.max, axis.flat, axis.fuzz,
Jeff Brown6f2fba42011-02-19 01:08:02 -08003785 axis.scale, axis.offset);
3786 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3787 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3788 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003789 }
3790}
3791
3792void JoystickInputMapper::configure() {
3793 InputMapper::configure();
3794
Jeff Brown6f2fba42011-02-19 01:08:02 -08003795 // Collect all axes.
3796 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3797 RawAbsoluteAxisInfo rawAxisInfo;
3798 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3799 if (rawAxisInfo.valid) {
3800 int32_t axisId;
3801 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
3802 if (!explicitlyMapped) {
3803 // Axis is not explicitly mapped, will choose a generic axis later.
3804 axisId = -1;
3805 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003806
Jeff Brown6f2fba42011-02-19 01:08:02 -08003807 Axis axis;
3808 if (isCenteredAxis(axisId)) {
3809 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3810 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
3811 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3812 scale, offset, -1.0f, 1.0f,
3813 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3814 } else {
3815 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3816 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3817 scale, 0.0f, 0.0f, 1.0f,
3818 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3819 }
3820
3821 // To eliminate noise while the joystick is at rest, filter out small variations
3822 // in axis values up front.
3823 axis.filter = axis.flat * 0.25f;
3824
3825 mAxes.add(abs, axis);
3826 }
3827 }
3828
3829 // If there are too many axes, start dropping them.
3830 // Prefer to keep explicitly mapped axes.
3831 if (mAxes.size() > PointerCoords::MAX_AXES) {
3832 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3833 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3834 pruneAxes(true);
3835 pruneAxes(false);
3836 }
3837
3838 // Assign generic axis ids to remaining axes.
3839 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3840 size_t numAxes = mAxes.size();
3841 for (size_t i = 0; i < numAxes; i++) {
3842 Axis& axis = mAxes.editValueAt(i);
3843 if (axis.axis < 0) {
3844 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3845 && haveAxis(nextGenericAxisId)) {
3846 nextGenericAxisId += 1;
3847 }
3848
3849 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
3850 axis.axis = nextGenericAxisId;
3851 nextGenericAxisId += 1;
3852 } else {
3853 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3854 "have already been assigned to other axes.",
3855 getDeviceName().string(), mAxes.keyAt(i));
3856 mAxes.removeItemsAt(i--);
3857 numAxes -= 1;
3858 }
3859 }
3860 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003861}
3862
Jeff Brown6f2fba42011-02-19 01:08:02 -08003863bool JoystickInputMapper::haveAxis(int32_t axis) {
3864 size_t numAxes = mAxes.size();
3865 for (size_t i = 0; i < numAxes; i++) {
3866 if (mAxes.valueAt(i).axis == axis) {
3867 return true;
3868 }
3869 }
3870 return false;
3871}
Jeff Browncb1404e2011-01-15 18:14:15 -08003872
Jeff Brown6f2fba42011-02-19 01:08:02 -08003873void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
3874 size_t i = mAxes.size();
3875 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
3876 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
3877 continue;
3878 }
3879 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
3880 getDeviceName().string(), mAxes.keyAt(i));
3881 mAxes.removeItemsAt(i);
3882 }
3883}
3884
3885bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
3886 switch (axis) {
3887 case AMOTION_EVENT_AXIS_X:
3888 case AMOTION_EVENT_AXIS_Y:
3889 case AMOTION_EVENT_AXIS_Z:
3890 case AMOTION_EVENT_AXIS_RX:
3891 case AMOTION_EVENT_AXIS_RY:
3892 case AMOTION_EVENT_AXIS_RZ:
3893 case AMOTION_EVENT_AXIS_HAT_X:
3894 case AMOTION_EVENT_AXIS_HAT_Y:
3895 case AMOTION_EVENT_AXIS_ORIENTATION:
3896 return true;
3897 default:
3898 return false;
3899 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003900}
3901
3902void JoystickInputMapper::reset() {
3903 // Recenter all axes.
3904 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08003905
Jeff Brown6f2fba42011-02-19 01:08:02 -08003906 size_t numAxes = mAxes.size();
3907 for (size_t i = 0; i < numAxes; i++) {
3908 Axis& axis = mAxes.editValueAt(i);
3909 axis.newValue = 0;
3910 }
3911
3912 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08003913
3914 InputMapper::reset();
3915}
3916
3917void JoystickInputMapper::process(const RawEvent* rawEvent) {
3918 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003919 case EV_ABS: {
3920 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
3921 if (index >= 0) {
3922 Axis& axis = mAxes.editValueAt(index);
3923 float newValue = rawEvent->value * axis.scale + axis.offset;
3924 if (newValue != axis.newValue) {
3925 axis.newValue = newValue;
3926 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003927 }
3928 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08003929 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003930
3931 case EV_SYN:
3932 switch (rawEvent->scanCode) {
3933 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08003934 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08003935 break;
3936 }
3937 break;
3938 }
3939}
3940
Jeff Brown6f2fba42011-02-19 01:08:02 -08003941void JoystickInputMapper::sync(nsecs_t when, bool force) {
3942 if (!force && !haveAxesChangedSignificantly()) {
3943 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08003944 }
3945
3946 int32_t metaState = mContext->getGlobalMetaState();
3947
Jeff Brown6f2fba42011-02-19 01:08:02 -08003948 PointerCoords pointerCoords;
3949 pointerCoords.clear();
3950
3951 size_t numAxes = mAxes.size();
3952 for (size_t i = 0; i < numAxes; i++) {
3953 Axis& axis = mAxes.editValueAt(i);
3954 pointerCoords.setAxisValue(axis.axis, axis.newValue);
3955 axis.oldValue = axis.newValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08003956 }
3957
Jeff Brown6f2fba42011-02-19 01:08:02 -08003958 int32_t pointerId = 0;
3959 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3960 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3961 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08003962}
3963
Jeff Brown6f2fba42011-02-19 01:08:02 -08003964bool JoystickInputMapper::haveAxesChangedSignificantly() {
3965 size_t numAxes = mAxes.size();
3966 for (size_t i = 0; i < numAxes; i++) {
3967 const Axis& axis = mAxes.valueAt(i);
3968 if (axis.newValue != axis.oldValue
3969 && fabs(axis.newValue - axis.oldValue) > axis.filter) {
3970 return true;
3971 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003972 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08003973 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08003974}
3975
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003976} // namespace android