blob: 05f40ba40029c79feee6ba20202b836334110d0d [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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brownfd035822010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700117
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700161 break;
162
Jeff Brown6d0fec22010-07-23 21:28:06 -0700163 default:
164 consumeEvent(rawEvent);
Jeff Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700197 return;
198 }
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700374 }
375 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Brown46b9ac02010-04-22 18:58:52 -0700377
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 mInputConfiguration.touchScreen = touchScreenConfig;
379 mInputConfiguration.keyboard = keyboardConfig;
380 mInputConfiguration.navigation = navigationConfig;
381 } // release state lock
382}
383
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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brownf2f48712010-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");
587 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
588 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
589 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
590 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
591 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
592 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
593 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
594 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
595 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
596 }
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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brownfd035822010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown51e7fe72010-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 Brown51e7fe72010-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 Brown51e7fe72010-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)) {
1064 info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f);
1065 info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f);
1066 }
1067 } else {
1068 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1069 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1070 }
1071 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001072}
1073
Jeff Brown83c09682010-12-23 17:50:18 -08001074void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001075 { // acquire lock
1076 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001077 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001078 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001079 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1080 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1081 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1082 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1083 } // release lock
1084}
1085
Jeff Brown83c09682010-12-23 17:50:18 -08001086void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001087 InputMapper::configure();
1088
1089 // Configure basic parameters.
1090 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001091
1092 // Configure device mode.
1093 switch (mParameters.mode) {
1094 case Parameters::MODE_POINTER:
1095 mSources = AINPUT_SOURCE_MOUSE;
1096 mXPrecision = 1.0f;
1097 mYPrecision = 1.0f;
1098 mXScale = 1.0f;
1099 mYScale = 1.0f;
1100 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1101 break;
1102 case Parameters::MODE_NAVIGATION:
1103 mSources = AINPUT_SOURCE_TRACKBALL;
1104 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1105 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1106 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1107 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1108 break;
1109 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001110}
1111
Jeff Brown83c09682010-12-23 17:50:18 -08001112void CursorInputMapper::configureParameters() {
1113 mParameters.mode = Parameters::MODE_POINTER;
1114 String8 cursorModeString;
1115 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1116 if (cursorModeString == "navigation") {
1117 mParameters.mode = Parameters::MODE_NAVIGATION;
1118 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1119 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1120 }
1121 }
1122
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001123 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001124 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001125 mParameters.orientationAware);
1126
Jeff Brown83c09682010-12-23 17:50:18 -08001127 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1128 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001129}
1130
Jeff Brown83c09682010-12-23 17:50:18 -08001131void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001132 dump.append(INDENT3 "Parameters:\n");
1133 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1134 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001135
1136 switch (mParameters.mode) {
1137 case Parameters::MODE_POINTER:
1138 dump.append(INDENT4 "Mode: pointer\n");
1139 break;
1140 case Parameters::MODE_NAVIGATION:
1141 dump.append(INDENT4 "Mode: navigation\n");
1142 break;
1143 default:
1144 assert(false);
1145 }
1146
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001147 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1148 toString(mParameters.orientationAware));
1149}
1150
Jeff Brown83c09682010-12-23 17:50:18 -08001151void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001152 mAccumulator.clear();
1153
Jeff Brown6328cdc2010-07-29 18:18:33 -07001154 mLocked.down = false;
1155 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001156}
1157
Jeff Brown83c09682010-12-23 17:50:18 -08001158void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001159 for (;;) {
1160 { // acquire lock
1161 AutoMutex _l(mLock);
1162
1163 if (! mLocked.down) {
1164 initializeLocked();
1165 break; // done
1166 }
1167 } // release lock
1168
Jeff Brown83c09682010-12-23 17:50:18 -08001169 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001170 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001171 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001172 mAccumulator.btnMouse = false;
1173 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001174 }
1175
Jeff Brown6d0fec22010-07-23 21:28:06 -07001176 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001177}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001178
Jeff Brown83c09682010-12-23 17:50:18 -08001179void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001180 switch (rawEvent->type) {
1181 case EV_KEY:
1182 switch (rawEvent->scanCode) {
1183 case BTN_MOUSE:
1184 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1185 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001186 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1187 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001188 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001189 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001190 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001191 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001192
Jeff Brown6d0fec22010-07-23 21:28:06 -07001193 case EV_REL:
1194 switch (rawEvent->scanCode) {
1195 case REL_X:
1196 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1197 mAccumulator.relX = rawEvent->value;
1198 break;
1199 case REL_Y:
1200 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1201 mAccumulator.relY = rawEvent->value;
1202 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001203 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001204 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001205
Jeff Brown6d0fec22010-07-23 21:28:06 -07001206 case EV_SYN:
1207 switch (rawEvent->scanCode) {
1208 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001209 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001210 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001211 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001212 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001213 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001214}
1215
Jeff Brown83c09682010-12-23 17:50:18 -08001216void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001217 uint32_t fields = mAccumulator.fields;
1218 if (fields == 0) {
1219 return; // no new state changes, so nothing to do
1220 }
1221
Jeff Brown6328cdc2010-07-29 18:18:33 -07001222 int motionEventAction;
1223 PointerCoords pointerCoords;
1224 nsecs_t downTime;
1225 { // acquire lock
1226 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001227
Jeff Brown6328cdc2010-07-29 18:18:33 -07001228 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1229
1230 if (downChanged) {
1231 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001232 if (!mLocked.down) {
1233 mLocked.down = true;
1234 mLocked.downTime = when;
1235 } else {
1236 downChanged = false;
1237 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001238 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001239 if (mLocked.down) {
1240 mLocked.down = false;
1241 } else {
1242 downChanged = false;
1243 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001244 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001245 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001246
Jeff Brown6328cdc2010-07-29 18:18:33 -07001247 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001248 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1249 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001250
Jeff Brown6328cdc2010-07-29 18:18:33 -07001251 if (downChanged) {
1252 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001253 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001254 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001255 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001256
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001257 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001258 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001259 // Rotate motion based on display orientation if needed.
1260 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1261 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001262 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1263 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001264 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001265 }
1266
1267 float temp;
1268 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001269 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001270 temp = deltaX;
1271 deltaX = deltaY;
1272 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001273 break;
1274
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001275 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001276 deltaX = -deltaX;
1277 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001278 break;
1279
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001280 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001281 temp = deltaX;
1282 deltaX = -deltaY;
1283 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001284 break;
1285 }
1286 }
Jeff Brown83c09682010-12-23 17:50:18 -08001287
1288 if (mPointerController != NULL) {
1289 mPointerController->move(deltaX, deltaY);
1290 if (downChanged) {
1291 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1292 }
1293 mPointerController->getPosition(&pointerCoords.x, &pointerCoords.y);
1294 } else {
1295 pointerCoords.x = deltaX;
1296 pointerCoords.y = deltaY;
1297 }
1298
1299 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1300 pointerCoords.size = 0;
1301 pointerCoords.touchMajor = 0;
1302 pointerCoords.touchMinor = 0;
1303 pointerCoords.toolMajor = 0;
1304 pointerCoords.toolMinor = 0;
1305 pointerCoords.orientation = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001306 } // release lock
1307
Jeff Brown6d0fec22010-07-23 21:28:06 -07001308 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001309 int32_t pointerId = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001310 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
Jeff Brown85a31762010-09-01 17:01:00 -07001311 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001312 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1313
1314 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001315}
1316
Jeff Brown83c09682010-12-23 17:50:18 -08001317int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001318 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1319 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1320 } else {
1321 return AKEY_STATE_UNKNOWN;
1322 }
1323}
1324
Jeff Brown6d0fec22010-07-23 21:28:06 -07001325
1326// --- TouchInputMapper ---
1327
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001328TouchInputMapper::TouchInputMapper(InputDevice* device) :
1329 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001330 mLocked.surfaceOrientation = -1;
1331 mLocked.surfaceWidth = -1;
1332 mLocked.surfaceHeight = -1;
1333
1334 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001335}
1336
1337TouchInputMapper::~TouchInputMapper() {
1338}
1339
1340uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001341 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001342}
1343
1344void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1345 InputMapper::populateDeviceInfo(info);
1346
Jeff Brown6328cdc2010-07-29 18:18:33 -07001347 { // acquire lock
1348 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001349
Jeff Brown6328cdc2010-07-29 18:18:33 -07001350 // Ensure surface information is up to date so that orientation changes are
1351 // noticed immediately.
1352 configureSurfaceLocked();
1353
1354 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1355 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001356
1357 if (mLocked.orientedRanges.havePressure) {
1358 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1359 mLocked.orientedRanges.pressure);
1360 }
1361
1362 if (mLocked.orientedRanges.haveSize) {
1363 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1364 mLocked.orientedRanges.size);
1365 }
1366
Jeff Brownc6d282b2010-10-14 21:42:15 -07001367 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown8d608662010-08-30 03:02:23 -07001368 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1369 mLocked.orientedRanges.touchMajor);
1370 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1371 mLocked.orientedRanges.touchMinor);
1372 }
1373
Jeff Brownc6d282b2010-10-14 21:42:15 -07001374 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown8d608662010-08-30 03:02:23 -07001375 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1376 mLocked.orientedRanges.toolMajor);
1377 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1378 mLocked.orientedRanges.toolMinor);
1379 }
1380
1381 if (mLocked.orientedRanges.haveOrientation) {
1382 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1383 mLocked.orientedRanges.orientation);
1384 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001385 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001386}
1387
Jeff Brownef3d7e82010-09-30 14:33:04 -07001388void TouchInputMapper::dump(String8& dump) {
1389 { // acquire lock
1390 AutoMutex _l(mLock);
1391 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001392 dumpParameters(dump);
1393 dumpVirtualKeysLocked(dump);
1394 dumpRawAxes(dump);
1395 dumpCalibration(dump);
1396 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001397 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001398 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1399 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1400 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1401 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1402 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1403 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1404 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1405 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1406 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1407 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1408 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1409 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1410 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1411 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001412 } // release lock
1413}
1414
Jeff Brown6328cdc2010-07-29 18:18:33 -07001415void TouchInputMapper::initializeLocked() {
1416 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001417 mLastTouch.clear();
1418 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001419
1420 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1421 mAveragingTouchFilter.historyStart[i] = 0;
1422 mAveragingTouchFilter.historyEnd[i] = 0;
1423 }
1424
1425 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001426
1427 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001428
1429 mLocked.orientedRanges.havePressure = false;
1430 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001431 mLocked.orientedRanges.haveTouchSize = false;
1432 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001433 mLocked.orientedRanges.haveOrientation = false;
1434}
1435
Jeff Brown6d0fec22010-07-23 21:28:06 -07001436void TouchInputMapper::configure() {
1437 InputMapper::configure();
1438
1439 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001440 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001441
Jeff Brown83c09682010-12-23 17:50:18 -08001442 // Configure sources.
1443 switch (mParameters.deviceType) {
1444 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1445 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1446 break;
1447 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1448 mSources = AINPUT_SOURCE_TOUCHPAD;
1449 break;
1450 default:
1451 assert(false);
1452 }
1453
Jeff Brown6d0fec22010-07-23 21:28:06 -07001454 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001455 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001456
1457 // Prepare input device calibration.
1458 parseCalibration();
1459 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001460
Jeff Brown6328cdc2010-07-29 18:18:33 -07001461 { // acquire lock
1462 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001463
Jeff Brown8d608662010-08-30 03:02:23 -07001464 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001465 configureSurfaceLocked();
1466 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001467}
1468
Jeff Brown8d608662010-08-30 03:02:23 -07001469void TouchInputMapper::configureParameters() {
1470 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1471 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1472 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001473 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001474
1475 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001476 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001477 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1478 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001479 if (deviceTypeString == "touchScreen") {
1480 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1481 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001482 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1483 }
1484 }
1485 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1486
1487 mParameters.orientationAware = isTouchScreen;
1488 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1489 mParameters.orientationAware);
1490
1491 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001492}
1493
Jeff Brownef3d7e82010-09-30 14:33:04 -07001494void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001495 dump.append(INDENT3 "Parameters:\n");
1496
1497 switch (mParameters.deviceType) {
1498 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1499 dump.append(INDENT4 "DeviceType: touchScreen\n");
1500 break;
1501 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1502 dump.append(INDENT4 "DeviceType: touchPad\n");
1503 break;
1504 default:
1505 assert(false);
1506 }
1507
1508 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1509 mParameters.associatedDisplayId);
1510 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1511 toString(mParameters.orientationAware));
1512
1513 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001514 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001515 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001516 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001517 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001518 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001519}
1520
Jeff Brown8d608662010-08-30 03:02:23 -07001521void TouchInputMapper::configureRawAxes() {
1522 mRawAxes.x.clear();
1523 mRawAxes.y.clear();
1524 mRawAxes.pressure.clear();
1525 mRawAxes.touchMajor.clear();
1526 mRawAxes.touchMinor.clear();
1527 mRawAxes.toolMajor.clear();
1528 mRawAxes.toolMinor.clear();
1529 mRawAxes.orientation.clear();
1530}
1531
Jeff Brownef3d7e82010-09-30 14:33:04 -07001532void TouchInputMapper::dumpRawAxes(String8& dump) {
1533 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001534 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1535 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1536 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1537 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1538 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1539 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1540 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1541 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001542}
1543
Jeff Brown6328cdc2010-07-29 18:18:33 -07001544bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001545 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001546 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001547 int32_t width = mRawAxes.x.getRange();
1548 int32_t height = mRawAxes.y.getRange();
1549
1550 if (mParameters.associatedDisplayId >= 0) {
1551 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1552 bool wantOrientation = mParameters.orientationAware;
1553
Jeff Brown6328cdc2010-07-29 18:18:33 -07001554 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001555 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1556 wantSize ? &width : NULL, wantSize ? &height : NULL,
1557 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001558 return false;
1559 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001560 }
1561
Jeff Brown6328cdc2010-07-29 18:18:33 -07001562 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001563 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001564 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001565 }
1566
Jeff Brown6328cdc2010-07-29 18:18:33 -07001567 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001568 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001569 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001570 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001571
Jeff Brown6328cdc2010-07-29 18:18:33 -07001572 mLocked.surfaceWidth = width;
1573 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001574
Jeff Brown8d608662010-08-30 03:02:23 -07001575 // Configure X and Y factors.
1576 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001577 mLocked.xOrigin = mCalibration.haveXOrigin
1578 ? mCalibration.xOrigin
1579 : mRawAxes.x.minValue;
1580 mLocked.yOrigin = mCalibration.haveYOrigin
1581 ? mCalibration.yOrigin
1582 : mRawAxes.y.minValue;
1583 mLocked.xScale = mCalibration.haveXScale
1584 ? mCalibration.xScale
1585 : float(width) / mRawAxes.x.getRange();
1586 mLocked.yScale = mCalibration.haveYScale
1587 ? mCalibration.yScale
1588 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001589 mLocked.xPrecision = 1.0f / mLocked.xScale;
1590 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001591
Jeff Brown6328cdc2010-07-29 18:18:33 -07001592 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001593 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001594 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001595 mLocked.xOrigin = 0;
1596 mLocked.yOrigin = 0;
1597 mLocked.xScale = 1.0f;
1598 mLocked.yScale = 1.0f;
1599 mLocked.xPrecision = 1.0f;
1600 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001601 }
1602
Jeff Brown8d608662010-08-30 03:02:23 -07001603 // Scale factor for terms that are not oriented in a particular axis.
1604 // If the pixels are square then xScale == yScale otherwise we fake it
1605 // by choosing an average.
1606 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001607
Jeff Brown8d608662010-08-30 03:02:23 -07001608 // Size of diagonal axis.
1609 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001610
Jeff Brown8d608662010-08-30 03:02:23 -07001611 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001612 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1613 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001614 mLocked.orientedRanges.touchMajor.min = 0;
1615 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1616 mLocked.orientedRanges.touchMajor.flat = 0;
1617 mLocked.orientedRanges.touchMajor.fuzz = 0;
1618 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1619 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001620
Jeff Brown8d608662010-08-30 03:02:23 -07001621 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001622 mLocked.toolSizeLinearScale = 0;
1623 mLocked.toolSizeLinearBias = 0;
1624 mLocked.toolSizeAreaScale = 0;
1625 mLocked.toolSizeAreaBias = 0;
1626 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1627 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1628 if (mCalibration.haveToolSizeLinearScale) {
1629 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001630 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001631 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001632 / mRawAxes.toolMajor.maxValue;
1633 }
1634
Jeff Brownc6d282b2010-10-14 21:42:15 -07001635 if (mCalibration.haveToolSizeLinearBias) {
1636 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1637 }
1638 } else if (mCalibration.toolSizeCalibration ==
1639 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1640 if (mCalibration.haveToolSizeLinearScale) {
1641 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1642 } else {
1643 mLocked.toolSizeLinearScale = min(width, height);
1644 }
1645
1646 if (mCalibration.haveToolSizeLinearBias) {
1647 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1648 }
1649
1650 if (mCalibration.haveToolSizeAreaScale) {
1651 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1652 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1653 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1654 }
1655
1656 if (mCalibration.haveToolSizeAreaBias) {
1657 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001658 }
1659 }
1660
Jeff Brownc6d282b2010-10-14 21:42:15 -07001661 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001662 mLocked.orientedRanges.toolMajor.min = 0;
1663 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1664 mLocked.orientedRanges.toolMajor.flat = 0;
1665 mLocked.orientedRanges.toolMajor.fuzz = 0;
1666 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1667 }
1668
1669 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001670 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001671 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1672 RawAbsoluteAxisInfo rawPressureAxis;
1673 switch (mCalibration.pressureSource) {
1674 case Calibration::PRESSURE_SOURCE_PRESSURE:
1675 rawPressureAxis = mRawAxes.pressure;
1676 break;
1677 case Calibration::PRESSURE_SOURCE_TOUCH:
1678 rawPressureAxis = mRawAxes.touchMajor;
1679 break;
1680 default:
1681 rawPressureAxis.clear();
1682 }
1683
Jeff Brown8d608662010-08-30 03:02:23 -07001684 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1685 || mCalibration.pressureCalibration
1686 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1687 if (mCalibration.havePressureScale) {
1688 mLocked.pressureScale = mCalibration.pressureScale;
1689 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1690 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1691 }
1692 }
1693
1694 mLocked.orientedRanges.havePressure = true;
1695 mLocked.orientedRanges.pressure.min = 0;
1696 mLocked.orientedRanges.pressure.max = 1.0;
1697 mLocked.orientedRanges.pressure.flat = 0;
1698 mLocked.orientedRanges.pressure.fuzz = 0;
1699 }
1700
1701 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001702 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001703 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001704 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1705 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1706 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1707 }
1708 }
1709
1710 mLocked.orientedRanges.haveSize = true;
1711 mLocked.orientedRanges.size.min = 0;
1712 mLocked.orientedRanges.size.max = 1.0;
1713 mLocked.orientedRanges.size.flat = 0;
1714 mLocked.orientedRanges.size.fuzz = 0;
1715 }
1716
1717 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001718 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001719 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001720 if (mCalibration.orientationCalibration
1721 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1722 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1723 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1724 }
1725 }
1726
1727 mLocked.orientedRanges.orientation.min = - M_PI_2;
1728 mLocked.orientedRanges.orientation.max = M_PI_2;
1729 mLocked.orientedRanges.orientation.flat = 0;
1730 mLocked.orientedRanges.orientation.fuzz = 0;
1731 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001732 }
1733
1734 if (orientationChanged || sizeChanged) {
1735 // Compute oriented surface dimensions, precision, and scales.
1736 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001737 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001738 case DISPLAY_ORIENTATION_90:
1739 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001740 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1741 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1742 mLocked.orientedXPrecision = mLocked.yPrecision;
1743 mLocked.orientedYPrecision = mLocked.xPrecision;
1744 orientedXScale = mLocked.yScale;
1745 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001746 break;
1747 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001748 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1749 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1750 mLocked.orientedXPrecision = mLocked.xPrecision;
1751 mLocked.orientedYPrecision = mLocked.yPrecision;
1752 orientedXScale = mLocked.xScale;
1753 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001754 break;
1755 }
1756
1757 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001758 mLocked.orientedRanges.x.min = 0;
1759 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1760 mLocked.orientedRanges.x.flat = 0;
1761 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001762
Jeff Brown6328cdc2010-07-29 18:18:33 -07001763 mLocked.orientedRanges.y.min = 0;
1764 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1765 mLocked.orientedRanges.y.flat = 0;
1766 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001767 }
1768
1769 return true;
1770}
1771
Jeff Brownef3d7e82010-09-30 14:33:04 -07001772void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1773 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1774 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1775 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001776}
1777
Jeff Brown6328cdc2010-07-29 18:18:33 -07001778void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001779 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001780
Jeff Brown8d608662010-08-30 03:02:23 -07001781 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001782 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001783
Jeff Brown6328cdc2010-07-29 18:18:33 -07001784 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001785
Jeff Brown6328cdc2010-07-29 18:18:33 -07001786 if (virtualKeyDefinitions.size() == 0) {
1787 return;
1788 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001789
Jeff Brown6328cdc2010-07-29 18:18:33 -07001790 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1791
Jeff Brown8d608662010-08-30 03:02:23 -07001792 int32_t touchScreenLeft = mRawAxes.x.minValue;
1793 int32_t touchScreenTop = mRawAxes.y.minValue;
1794 int32_t touchScreenWidth = mRawAxes.x.getRange();
1795 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001796
1797 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001798 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001799 virtualKeyDefinitions[i];
1800
1801 mLocked.virtualKeys.add();
1802 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1803
1804 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1805 int32_t keyCode;
1806 uint32_t flags;
1807 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1808 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001809 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1810 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001811 mLocked.virtualKeys.pop(); // drop the key
1812 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001813 }
1814
Jeff Brown6328cdc2010-07-29 18:18:33 -07001815 virtualKey.keyCode = keyCode;
1816 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001817
Jeff Brown6328cdc2010-07-29 18:18:33 -07001818 // convert the key definition's display coordinates into touch coordinates for a hit box
1819 int32_t halfWidth = virtualKeyDefinition.width / 2;
1820 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001821
Jeff Brown6328cdc2010-07-29 18:18:33 -07001822 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1823 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1824 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1825 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1826 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1827 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1828 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1829 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001830
Jeff Brownef3d7e82010-09-30 14:33:04 -07001831 }
1832}
1833
1834void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1835 if (!mLocked.virtualKeys.isEmpty()) {
1836 dump.append(INDENT3 "Virtual Keys:\n");
1837
1838 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1839 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1840 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1841 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1842 i, virtualKey.scanCode, virtualKey.keyCode,
1843 virtualKey.hitLeft, virtualKey.hitRight,
1844 virtualKey.hitTop, virtualKey.hitBottom);
1845 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001846 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001847}
1848
Jeff Brown8d608662010-08-30 03:02:23 -07001849void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001850 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001851 Calibration& out = mCalibration;
1852
Jeff Brown511ee5f2010-10-18 13:32:20 -07001853 // Position
1854 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1855 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1856 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1857 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1858
Jeff Brownc6d282b2010-10-14 21:42:15 -07001859 // Touch Size
1860 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1861 String8 touchSizeCalibrationString;
1862 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1863 if (touchSizeCalibrationString == "none") {
1864 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1865 } else if (touchSizeCalibrationString == "geometric") {
1866 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1867 } else if (touchSizeCalibrationString == "pressure") {
1868 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1869 } else if (touchSizeCalibrationString != "default") {
1870 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1871 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001872 }
1873 }
1874
Jeff Brownc6d282b2010-10-14 21:42:15 -07001875 // Tool Size
1876 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1877 String8 toolSizeCalibrationString;
1878 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1879 if (toolSizeCalibrationString == "none") {
1880 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1881 } else if (toolSizeCalibrationString == "geometric") {
1882 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1883 } else if (toolSizeCalibrationString == "linear") {
1884 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1885 } else if (toolSizeCalibrationString == "area") {
1886 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1887 } else if (toolSizeCalibrationString != "default") {
1888 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1889 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001890 }
1891 }
1892
Jeff Brownc6d282b2010-10-14 21:42:15 -07001893 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1894 out.toolSizeLinearScale);
1895 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1896 out.toolSizeLinearBias);
1897 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1898 out.toolSizeAreaScale);
1899 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1900 out.toolSizeAreaBias);
1901 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1902 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07001903
1904 // Pressure
1905 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1906 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001907 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001908 if (pressureCalibrationString == "none") {
1909 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1910 } else if (pressureCalibrationString == "physical") {
1911 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1912 } else if (pressureCalibrationString == "amplitude") {
1913 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1914 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001915 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001916 pressureCalibrationString.string());
1917 }
1918 }
1919
1920 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1921 String8 pressureSourceString;
1922 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1923 if (pressureSourceString == "pressure") {
1924 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1925 } else if (pressureSourceString == "touch") {
1926 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1927 } else if (pressureSourceString != "default") {
1928 LOGW("Invalid value for touch.pressure.source: '%s'",
1929 pressureSourceString.string());
1930 }
1931 }
1932
1933 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1934 out.pressureScale);
1935
1936 // Size
1937 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1938 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001939 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001940 if (sizeCalibrationString == "none") {
1941 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1942 } else if (sizeCalibrationString == "normalized") {
1943 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1944 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001945 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001946 sizeCalibrationString.string());
1947 }
1948 }
1949
1950 // Orientation
1951 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1952 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001953 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001954 if (orientationCalibrationString == "none") {
1955 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1956 } else if (orientationCalibrationString == "interpolated") {
1957 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08001958 } else if (orientationCalibrationString == "vector") {
1959 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001960 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001961 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001962 orientationCalibrationString.string());
1963 }
1964 }
1965}
1966
1967void TouchInputMapper::resolveCalibration() {
1968 // Pressure
1969 switch (mCalibration.pressureSource) {
1970 case Calibration::PRESSURE_SOURCE_DEFAULT:
1971 if (mRawAxes.pressure.valid) {
1972 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1973 } else if (mRawAxes.touchMajor.valid) {
1974 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1975 }
1976 break;
1977
1978 case Calibration::PRESSURE_SOURCE_PRESSURE:
1979 if (! mRawAxes.pressure.valid) {
1980 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1981 "the pressure axis is not available.");
1982 }
1983 break;
1984
1985 case Calibration::PRESSURE_SOURCE_TOUCH:
1986 if (! mRawAxes.touchMajor.valid) {
1987 LOGW("Calibration property touch.pressure.source is 'touch' but "
1988 "the touchMajor axis is not available.");
1989 }
1990 break;
1991
1992 default:
1993 break;
1994 }
1995
1996 switch (mCalibration.pressureCalibration) {
1997 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1998 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1999 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2000 } else {
2001 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2002 }
2003 break;
2004
2005 default:
2006 break;
2007 }
2008
Jeff Brownc6d282b2010-10-14 21:42:15 -07002009 // Tool Size
2010 switch (mCalibration.toolSizeCalibration) {
2011 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002012 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002013 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002014 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002015 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002016 }
2017 break;
2018
2019 default:
2020 break;
2021 }
2022
Jeff Brownc6d282b2010-10-14 21:42:15 -07002023 // Touch Size
2024 switch (mCalibration.touchSizeCalibration) {
2025 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002026 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002027 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2028 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002029 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002030 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002031 }
2032 break;
2033
2034 default:
2035 break;
2036 }
2037
2038 // Size
2039 switch (mCalibration.sizeCalibration) {
2040 case Calibration::SIZE_CALIBRATION_DEFAULT:
2041 if (mRawAxes.toolMajor.valid) {
2042 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2043 } else {
2044 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2045 }
2046 break;
2047
2048 default:
2049 break;
2050 }
2051
2052 // Orientation
2053 switch (mCalibration.orientationCalibration) {
2054 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2055 if (mRawAxes.orientation.valid) {
2056 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2057 } else {
2058 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2059 }
2060 break;
2061
2062 default:
2063 break;
2064 }
2065}
2066
Jeff Brownef3d7e82010-09-30 14:33:04 -07002067void TouchInputMapper::dumpCalibration(String8& dump) {
2068 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002069
Jeff Brown511ee5f2010-10-18 13:32:20 -07002070 // Position
2071 if (mCalibration.haveXOrigin) {
2072 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2073 }
2074 if (mCalibration.haveYOrigin) {
2075 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2076 }
2077 if (mCalibration.haveXScale) {
2078 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2079 }
2080 if (mCalibration.haveYScale) {
2081 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2082 }
2083
Jeff Brownc6d282b2010-10-14 21:42:15 -07002084 // Touch Size
2085 switch (mCalibration.touchSizeCalibration) {
2086 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2087 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002088 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002089 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2090 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002091 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002092 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2093 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002094 break;
2095 default:
2096 assert(false);
2097 }
2098
Jeff Brownc6d282b2010-10-14 21:42:15 -07002099 // Tool Size
2100 switch (mCalibration.toolSizeCalibration) {
2101 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2102 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002103 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002104 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2105 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002106 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002107 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2108 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2109 break;
2110 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2111 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002112 break;
2113 default:
2114 assert(false);
2115 }
2116
Jeff Brownc6d282b2010-10-14 21:42:15 -07002117 if (mCalibration.haveToolSizeLinearScale) {
2118 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2119 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002120 }
2121
Jeff Brownc6d282b2010-10-14 21:42:15 -07002122 if (mCalibration.haveToolSizeLinearBias) {
2123 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2124 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002125 }
2126
Jeff Brownc6d282b2010-10-14 21:42:15 -07002127 if (mCalibration.haveToolSizeAreaScale) {
2128 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2129 mCalibration.toolSizeAreaScale);
2130 }
2131
2132 if (mCalibration.haveToolSizeAreaBias) {
2133 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2134 mCalibration.toolSizeAreaBias);
2135 }
2136
2137 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002138 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002139 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002140 }
2141
2142 // Pressure
2143 switch (mCalibration.pressureCalibration) {
2144 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002145 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002146 break;
2147 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002148 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002149 break;
2150 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002151 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002152 break;
2153 default:
2154 assert(false);
2155 }
2156
2157 switch (mCalibration.pressureSource) {
2158 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002159 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002160 break;
2161 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002162 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002163 break;
2164 case Calibration::PRESSURE_SOURCE_DEFAULT:
2165 break;
2166 default:
2167 assert(false);
2168 }
2169
2170 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002171 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2172 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002173 }
2174
2175 // Size
2176 switch (mCalibration.sizeCalibration) {
2177 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002178 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002179 break;
2180 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002181 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002182 break;
2183 default:
2184 assert(false);
2185 }
2186
2187 // Orientation
2188 switch (mCalibration.orientationCalibration) {
2189 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002190 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002191 break;
2192 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002193 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002194 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002195 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2196 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2197 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002198 default:
2199 assert(false);
2200 }
2201}
2202
Jeff Brown6d0fec22010-07-23 21:28:06 -07002203void TouchInputMapper::reset() {
2204 // Synthesize touch up event if touch is currently down.
2205 // This will also take care of finishing virtual key processing if needed.
2206 if (mLastTouch.pointerCount != 0) {
2207 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2208 mCurrentTouch.clear();
2209 syncTouch(when, true);
2210 }
2211
Jeff Brown6328cdc2010-07-29 18:18:33 -07002212 { // acquire lock
2213 AutoMutex _l(mLock);
2214 initializeLocked();
2215 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002216
Jeff Brown6328cdc2010-07-29 18:18:33 -07002217 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002218}
2219
2220void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002221 uint32_t policyFlags = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002222
Jeff Brown6328cdc2010-07-29 18:18:33 -07002223 // Preprocess pointer data.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002224
Jeff Brown6d0fec22010-07-23 21:28:06 -07002225 if (mParameters.useBadTouchFilter) {
2226 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002227 havePointerIds = false;
2228 }
2229 }
2230
Jeff Brown6d0fec22010-07-23 21:28:06 -07002231 if (mParameters.useJumpyTouchFilter) {
2232 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002233 havePointerIds = false;
2234 }
2235 }
2236
2237 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002238 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002239 }
2240
Jeff Brown6d0fec22010-07-23 21:28:06 -07002241 TouchData temp;
2242 TouchData* savedTouch;
2243 if (mParameters.useAveragingTouchFilter) {
2244 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002245 savedTouch = & temp;
2246
Jeff Brown6d0fec22010-07-23 21:28:06 -07002247 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002248 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002249 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002250 }
2251
Jeff Brown6328cdc2010-07-29 18:18:33 -07002252 // Process touches and virtual keys.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002253
Jeff Brown6d0fec22010-07-23 21:28:06 -07002254 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2255 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002256 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002257 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002258 }
2259
Jeff Brown6328cdc2010-07-29 18:18:33 -07002260 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002261
Jeff Brown6d0fec22010-07-23 21:28:06 -07002262 if (touchResult == DROP_STROKE) {
2263 mLastTouch.clear();
2264 } else {
2265 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002266 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002267}
2268
Jeff Brown6d0fec22010-07-23 21:28:06 -07002269TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2270 nsecs_t when, uint32_t policyFlags) {
2271 int32_t keyEventAction, keyEventFlags;
2272 int32_t keyCode, scanCode, downTime;
2273 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002274
Jeff Brown6328cdc2010-07-29 18:18:33 -07002275 { // acquire lock
2276 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002277
Jeff Brown6328cdc2010-07-29 18:18:33 -07002278 // Update surface size and orientation, including virtual key positions.
2279 if (! configureSurfaceLocked()) {
2280 return DROP_STROKE;
2281 }
2282
2283 // Check for virtual key press.
2284 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002285 if (mCurrentTouch.pointerCount == 0) {
2286 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002287 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002288#if DEBUG_VIRTUAL_KEYS
2289 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002290 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002291#endif
2292 keyEventAction = AKEY_EVENT_ACTION_UP;
2293 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2294 touchResult = SKIP_TOUCH;
2295 goto DispatchVirtualKey;
2296 }
2297
2298 if (mCurrentTouch.pointerCount == 1) {
2299 int32_t x = mCurrentTouch.pointers[0].x;
2300 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002301 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2302 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002303 // Pointer is still within the space of the virtual key.
2304 return SKIP_TOUCH;
2305 }
2306 }
2307
2308 // Pointer left virtual key area or another pointer also went down.
2309 // Send key cancellation and drop the stroke so subsequent motions will be
2310 // considered fresh downs. This is useful when the user swipes away from the
2311 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002312 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002313#if DEBUG_VIRTUAL_KEYS
2314 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002315 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002316#endif
2317 keyEventAction = AKEY_EVENT_ACTION_UP;
2318 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2319 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002320
2321 // Check whether the pointer moved inside the display area where we should
2322 // start a new stroke.
2323 int32_t x = mCurrentTouch.pointers[0].x;
2324 int32_t y = mCurrentTouch.pointers[0].y;
2325 if (isPointInsideSurfaceLocked(x, y)) {
2326 mLastTouch.clear();
2327 touchResult = DISPATCH_TOUCH;
2328 } else {
2329 touchResult = DROP_STROKE;
2330 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002331 } else {
2332 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2333 // Pointer just went down. Handle off-screen touches, if needed.
2334 int32_t x = mCurrentTouch.pointers[0].x;
2335 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002336 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002337 // If exactly one pointer went down, check for virtual key hit.
2338 // Otherwise we will drop the entire stroke.
2339 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002340 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002341 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002342 if (mContext->shouldDropVirtualKey(when, getDevice(),
2343 virtualKey->keyCode, virtualKey->scanCode)) {
2344 return DROP_STROKE;
2345 }
2346
Jeff Brown6328cdc2010-07-29 18:18:33 -07002347 mLocked.currentVirtualKey.down = true;
2348 mLocked.currentVirtualKey.downTime = when;
2349 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2350 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002351#if DEBUG_VIRTUAL_KEYS
2352 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002353 mLocked.currentVirtualKey.keyCode,
2354 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002355#endif
2356 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2357 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2358 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2359 touchResult = SKIP_TOUCH;
2360 goto DispatchVirtualKey;
2361 }
2362 }
2363 return DROP_STROKE;
2364 }
2365 }
2366 return DISPATCH_TOUCH;
2367 }
2368
2369 DispatchVirtualKey:
2370 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002371 keyCode = mLocked.currentVirtualKey.keyCode;
2372 scanCode = mLocked.currentVirtualKey.scanCode;
2373 downTime = mLocked.currentVirtualKey.downTime;
2374 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002375
2376 // Dispatch virtual key.
2377 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002378 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002379 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2380 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2381 return touchResult;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002382}
2383
Jeff Brownfe508922011-01-18 15:10:10 -08002384void TouchInputMapper::detectGestures(nsecs_t when) {
2385 // Disable all virtual key touches that happen within a short time interval of the
2386 // most recent touch. The idea is to filter out stray virtual key presses when
2387 // interacting with the touch screen.
2388 //
2389 // Problems we're trying to solve:
2390 //
2391 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2392 // virtual key area that is implemented by a separate touch panel and accidentally
2393 // triggers a virtual key.
2394 //
2395 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2396 // area and accidentally triggers a virtual key. This often happens when virtual keys
2397 // are layed out below the screen near to where the on screen keyboard's space bar
2398 // is displayed.
2399 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2400 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2401 }
2402}
2403
Jeff Brown6d0fec22010-07-23 21:28:06 -07002404void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2405 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2406 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002407 if (currentPointerCount == 0 && lastPointerCount == 0) {
2408 return; // nothing to do!
2409 }
2410
Jeff Brown6d0fec22010-07-23 21:28:06 -07002411 BitSet32 currentIdBits = mCurrentTouch.idBits;
2412 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002413
2414 if (currentIdBits == lastIdBits) {
2415 // No pointer id changes so this is a move event.
2416 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002417 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002418 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002419 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002420 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002421 // There may be pointers going up and pointers going down and pointers moving
2422 // all at the same time.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002423 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2424 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2425 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002426 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002427
Jeff Brownc3db8582010-10-20 15:33:38 -07002428 // Produce an intermediate representation of the touch data that consists of the
2429 // old location of pointers that have just gone up and the new location of pointers that
2430 // have just moved but omits the location of pointers that have just gone down.
2431 TouchData interimTouch;
2432 interimTouch.copyFrom(mLastTouch);
2433
2434 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2435 bool moveNeeded = false;
2436 while (!moveIdBits.isEmpty()) {
2437 uint32_t moveId = moveIdBits.firstMarkedBit();
2438 moveIdBits.clearBit(moveId);
2439
2440 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2441 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2442 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2443 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2444 moveNeeded = true;
2445 }
2446 }
2447
2448 // Dispatch pointer up events using the interim pointer locations.
2449 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002450 uint32_t upId = upIdBits.firstMarkedBit();
2451 upIdBits.clearBit(upId);
2452 BitSet32 oldActiveIdBits = activeIdBits;
2453 activeIdBits.clearBit(upId);
2454
2455 int32_t motionEventAction;
2456 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002457 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002458 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002459 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002460 }
2461
Jeff Brownc3db8582010-10-20 15:33:38 -07002462 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002463 oldActiveIdBits, upId, pointerCount, motionEventAction);
2464 pointerCount -= 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002465 }
2466
Jeff Brownc3db8582010-10-20 15:33:38 -07002467 // Dispatch move events if any of the remaining pointers moved from their old locations.
2468 // Although applications receive new locations as part of individual pointer up
2469 // events, they do not generally handle them except when presented in a move event.
2470 if (moveNeeded) {
2471 dispatchTouch(when, policyFlags, &mCurrentTouch,
2472 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2473 }
2474
2475 // Dispatch pointer down events using the new pointer locations.
2476 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002477 uint32_t downId = downIdBits.firstMarkedBit();
2478 downIdBits.clearBit(downId);
2479 BitSet32 oldActiveIdBits = activeIdBits;
2480 activeIdBits.markBit(downId);
2481
2482 int32_t motionEventAction;
2483 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002484 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002485 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002486 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002487 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002488 }
2489
Jeff Brown8d608662010-08-30 03:02:23 -07002490 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002491 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002492 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002493 }
2494 }
2495}
2496
Jeff Brown6d0fec22010-07-23 21:28:06 -07002497void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002498 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002499 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002500 int32_t pointerIds[MAX_POINTERS];
2501 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac02010-04-22 18:58:52 -07002502 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002503 float xPrecision, yPrecision;
2504
2505 { // acquire lock
2506 AutoMutex _l(mLock);
2507
2508 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2509 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002510 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002511 uint32_t id = idBits.firstMarkedBit();
2512 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002513 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002514
Jeff Brown8d608662010-08-30 03:02:23 -07002515 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002516
Jeff Brown8d608662010-08-30 03:02:23 -07002517 // X and Y
2518 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2519 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002520
Jeff Brown8d608662010-08-30 03:02:23 -07002521 // ToolMajor and ToolMinor
2522 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002523 switch (mCalibration.toolSizeCalibration) {
2524 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002525 toolMajor = in.toolMajor * mLocked.geometricScale;
2526 if (mRawAxes.toolMinor.valid) {
2527 toolMinor = in.toolMinor * mLocked.geometricScale;
2528 } else {
2529 toolMinor = toolMajor;
2530 }
2531 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002532 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002533 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002534 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002535 : 0;
2536 if (mRawAxes.toolMinor.valid) {
2537 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002538 ? in.toolMinor * mLocked.toolSizeLinearScale
2539 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002540 : 0;
2541 } else {
2542 toolMinor = toolMajor;
2543 }
2544 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002545 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2546 if (in.toolMajor != 0) {
2547 float diameter = sqrtf(in.toolMajor
2548 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2549 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2550 } else {
2551 toolMajor = 0;
2552 }
2553 toolMinor = toolMajor;
2554 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002555 default:
2556 toolMajor = 0;
2557 toolMinor = 0;
2558 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002559 }
2560
Jeff Brownc6d282b2010-10-14 21:42:15 -07002561 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002562 toolMajor /= pointerCount;
2563 toolMinor /= pointerCount;
2564 }
2565
2566 // Pressure
2567 float rawPressure;
2568 switch (mCalibration.pressureSource) {
2569 case Calibration::PRESSURE_SOURCE_PRESSURE:
2570 rawPressure = in.pressure;
2571 break;
2572 case Calibration::PRESSURE_SOURCE_TOUCH:
2573 rawPressure = in.touchMajor;
2574 break;
2575 default:
2576 rawPressure = 0;
2577 }
2578
2579 float pressure;
2580 switch (mCalibration.pressureCalibration) {
2581 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2582 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2583 pressure = rawPressure * mLocked.pressureScale;
2584 break;
2585 default:
2586 pressure = 1;
2587 break;
2588 }
2589
2590 // TouchMajor and TouchMinor
2591 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002592 switch (mCalibration.touchSizeCalibration) {
2593 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002594 touchMajor = in.touchMajor * mLocked.geometricScale;
2595 if (mRawAxes.touchMinor.valid) {
2596 touchMinor = in.touchMinor * mLocked.geometricScale;
2597 } else {
2598 touchMinor = touchMajor;
2599 }
2600 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002601 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002602 touchMajor = toolMajor * pressure;
2603 touchMinor = toolMinor * pressure;
2604 break;
2605 default:
2606 touchMajor = 0;
2607 touchMinor = 0;
2608 break;
2609 }
2610
2611 if (touchMajor > toolMajor) {
2612 touchMajor = toolMajor;
2613 }
2614 if (touchMinor > toolMinor) {
2615 touchMinor = toolMinor;
2616 }
2617
2618 // Size
2619 float size;
2620 switch (mCalibration.sizeCalibration) {
2621 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2622 float rawSize = mRawAxes.toolMinor.valid
2623 ? avg(in.toolMajor, in.toolMinor)
2624 : in.toolMajor;
2625 size = rawSize * mLocked.sizeScale;
2626 break;
2627 }
2628 default:
2629 size = 0;
2630 break;
2631 }
2632
2633 // Orientation
2634 float orientation;
2635 switch (mCalibration.orientationCalibration) {
2636 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2637 orientation = in.orientation * mLocked.orientationScale;
2638 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002639 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2640 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2641 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2642 if (c1 != 0 || c2 != 0) {
2643 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002644 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2645 touchMajor *= scale;
2646 touchMinor /= scale;
2647 toolMajor *= scale;
2648 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002649 } else {
2650 orientation = 0;
2651 }
2652 break;
2653 }
Jeff Brown8d608662010-08-30 03:02:23 -07002654 default:
2655 orientation = 0;
2656 }
2657
2658 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002659 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002660 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002661 float xTemp = x;
2662 x = y;
2663 y = mLocked.surfaceWidth - xTemp;
2664 orientation -= M_PI_2;
2665 if (orientation < - M_PI_2) {
2666 orientation += M_PI;
2667 }
2668 break;
2669 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002670 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002671 x = mLocked.surfaceWidth - x;
2672 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002673 break;
2674 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002675 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002676 float xTemp = x;
2677 x = mLocked.surfaceHeight - y;
2678 y = xTemp;
2679 orientation += M_PI_2;
2680 if (orientation > M_PI_2) {
2681 orientation -= M_PI;
2682 }
2683 break;
2684 }
2685 }
2686
Jeff Brown8d608662010-08-30 03:02:23 -07002687 // Write output coords.
2688 PointerCoords& out = pointerCoords[outIndex];
2689 out.x = x;
2690 out.y = y;
2691 out.pressure = pressure;
2692 out.size = size;
2693 out.touchMajor = touchMajor;
2694 out.touchMinor = touchMinor;
2695 out.toolMajor = toolMajor;
2696 out.toolMinor = toolMinor;
2697 out.orientation = orientation;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002698
Jeff Brown8d608662010-08-30 03:02:23 -07002699 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002700
2701 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002702 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002703 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002704 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002705
2706 // Check edge flags by looking only at the first pointer since the flags are
2707 // global to the event.
2708 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2709 if (pointerCoords[0].x <= 0) {
2710 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2711 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2712 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2713 }
2714 if (pointerCoords[0].y <= 0) {
2715 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2716 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2717 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2718 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002719 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002720
2721 xPrecision = mLocked.orientedXPrecision;
2722 yPrecision = mLocked.orientedYPrecision;
2723 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07002724
Jeff Brown83c09682010-12-23 17:50:18 -08002725 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002726 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002727 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002728 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002729}
2730
Jeff Brown6328cdc2010-07-29 18:18:33 -07002731bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002732 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2733 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2734 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002735 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002736 return true;
2737}
2738
Jeff Brown6328cdc2010-07-29 18:18:33 -07002739const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2740 int32_t x, int32_t y) {
2741 size_t numVirtualKeys = mLocked.virtualKeys.size();
2742 for (size_t i = 0; i < numVirtualKeys; i++) {
2743 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002744
2745#if DEBUG_VIRTUAL_KEYS
2746 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2747 "left=%d, top=%d, right=%d, bottom=%d",
2748 x, y,
2749 virtualKey.keyCode, virtualKey.scanCode,
2750 virtualKey.hitLeft, virtualKey.hitTop,
2751 virtualKey.hitRight, virtualKey.hitBottom);
2752#endif
2753
2754 if (virtualKey.isHit(x, y)) {
2755 return & virtualKey;
2756 }
2757 }
2758
2759 return NULL;
2760}
2761
2762void TouchInputMapper::calculatePointerIds() {
2763 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2764 uint32_t lastPointerCount = mLastTouch.pointerCount;
2765
2766 if (currentPointerCount == 0) {
2767 // No pointers to assign.
2768 mCurrentTouch.idBits.clear();
2769 } else if (lastPointerCount == 0) {
2770 // All pointers are new.
2771 mCurrentTouch.idBits.clear();
2772 for (uint32_t i = 0; i < currentPointerCount; i++) {
2773 mCurrentTouch.pointers[i].id = i;
2774 mCurrentTouch.idToIndex[i] = i;
2775 mCurrentTouch.idBits.markBit(i);
2776 }
2777 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2778 // Only one pointer and no change in count so it must have the same id as before.
2779 uint32_t id = mLastTouch.pointers[0].id;
2780 mCurrentTouch.pointers[0].id = id;
2781 mCurrentTouch.idToIndex[id] = 0;
2782 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2783 } else {
2784 // General case.
2785 // We build a heap of squared euclidean distances between current and last pointers
2786 // associated with the current and last pointer indices. Then, we find the best
2787 // match (by distance) for each current pointer.
2788 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2789
2790 uint32_t heapSize = 0;
2791 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2792 currentPointerIndex++) {
2793 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2794 lastPointerIndex++) {
2795 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2796 - mLastTouch.pointers[lastPointerIndex].x;
2797 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2798 - mLastTouch.pointers[lastPointerIndex].y;
2799
2800 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2801
2802 // Insert new element into the heap (sift up).
2803 heap[heapSize].currentPointerIndex = currentPointerIndex;
2804 heap[heapSize].lastPointerIndex = lastPointerIndex;
2805 heap[heapSize].distance = distance;
2806 heapSize += 1;
2807 }
2808 }
2809
2810 // Heapify
2811 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2812 startIndex -= 1;
2813 for (uint32_t parentIndex = startIndex; ;) {
2814 uint32_t childIndex = parentIndex * 2 + 1;
2815 if (childIndex >= heapSize) {
2816 break;
2817 }
2818
2819 if (childIndex + 1 < heapSize
2820 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2821 childIndex += 1;
2822 }
2823
2824 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2825 break;
2826 }
2827
2828 swap(heap[parentIndex], heap[childIndex]);
2829 parentIndex = childIndex;
2830 }
2831 }
2832
2833#if DEBUG_POINTER_ASSIGNMENT
2834 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2835 for (size_t i = 0; i < heapSize; i++) {
2836 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2837 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2838 heap[i].distance);
2839 }
2840#endif
2841
2842 // Pull matches out by increasing order of distance.
2843 // To avoid reassigning pointers that have already been matched, the loop keeps track
2844 // of which last and current pointers have been matched using the matchedXXXBits variables.
2845 // It also tracks the used pointer id bits.
2846 BitSet32 matchedLastBits(0);
2847 BitSet32 matchedCurrentBits(0);
2848 BitSet32 usedIdBits(0);
2849 bool first = true;
2850 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2851 for (;;) {
2852 if (first) {
2853 // The first time through the loop, we just consume the root element of
2854 // the heap (the one with smallest distance).
2855 first = false;
2856 } else {
2857 // Previous iterations consumed the root element of the heap.
2858 // Pop root element off of the heap (sift down).
2859 heapSize -= 1;
2860 assert(heapSize > 0);
2861
2862 // Sift down.
2863 heap[0] = heap[heapSize];
2864 for (uint32_t parentIndex = 0; ;) {
2865 uint32_t childIndex = parentIndex * 2 + 1;
2866 if (childIndex >= heapSize) {
2867 break;
2868 }
2869
2870 if (childIndex + 1 < heapSize
2871 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2872 childIndex += 1;
2873 }
2874
2875 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2876 break;
2877 }
2878
2879 swap(heap[parentIndex], heap[childIndex]);
2880 parentIndex = childIndex;
2881 }
2882
2883#if DEBUG_POINTER_ASSIGNMENT
2884 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2885 for (size_t i = 0; i < heapSize; i++) {
2886 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2887 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2888 heap[i].distance);
2889 }
2890#endif
2891 }
2892
2893 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2894 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2895
2896 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2897 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2898
2899 matchedCurrentBits.markBit(currentPointerIndex);
2900 matchedLastBits.markBit(lastPointerIndex);
2901
2902 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2903 mCurrentTouch.pointers[currentPointerIndex].id = id;
2904 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2905 usedIdBits.markBit(id);
2906
2907#if DEBUG_POINTER_ASSIGNMENT
2908 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2909 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2910#endif
2911 break;
2912 }
2913 }
2914
2915 // Assign fresh ids to new pointers.
2916 if (currentPointerCount > lastPointerCount) {
2917 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2918 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2919 uint32_t id = usedIdBits.firstUnmarkedBit();
2920
2921 mCurrentTouch.pointers[currentPointerIndex].id = id;
2922 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2923 usedIdBits.markBit(id);
2924
2925#if DEBUG_POINTER_ASSIGNMENT
2926 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2927 currentPointerIndex, id);
2928#endif
2929
2930 if (--i == 0) break; // done
2931 matchedCurrentBits.markBit(currentPointerIndex);
2932 }
2933 }
2934
2935 // Fix id bits.
2936 mCurrentTouch.idBits = usedIdBits;
2937 }
2938}
2939
2940/* Special hack for devices that have bad screen data: if one of the
2941 * points has moved more than a screen height from the last position,
2942 * then drop it. */
2943bool TouchInputMapper::applyBadTouchFilter() {
2944 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002945 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002946 return false;
2947 }
2948
2949 uint32_t pointerCount = mCurrentTouch.pointerCount;
2950
2951 // Nothing to do if there are no points.
2952 if (pointerCount == 0) {
2953 return false;
2954 }
2955
2956 // Don't do anything if a finger is going down or up. We run
2957 // here before assigning pointer IDs, so there isn't a good
2958 // way to do per-finger matching.
2959 if (pointerCount != mLastTouch.pointerCount) {
2960 return false;
2961 }
2962
2963 // We consider a single movement across more than a 7/16 of
2964 // the long size of the screen to be bad. This was a magic value
2965 // determined by looking at the maximum distance it is feasible
2966 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07002967 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002968
2969 // XXX The original code in InputDevice.java included commented out
2970 // code for testing the X axis. Note that when we drop a point
2971 // we don't actually restore the old X either. Strange.
2972 // The old code also tries to track when bad points were previously
2973 // detected but it turns out that due to the placement of a "break"
2974 // at the end of the loop, we never set mDroppedBadPoint to true
2975 // so it is effectively dead code.
2976 // Need to figure out if the old code is busted or just overcomplicated
2977 // but working as intended.
2978
2979 // Look through all new points and see if any are farther than
2980 // acceptable from all previous points.
2981 for (uint32_t i = pointerCount; i-- > 0; ) {
2982 int32_t y = mCurrentTouch.pointers[i].y;
2983 int32_t closestY = INT_MAX;
2984 int32_t closestDeltaY = 0;
2985
2986#if DEBUG_HACKS
2987 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2988#endif
2989
2990 for (uint32_t j = pointerCount; j-- > 0; ) {
2991 int32_t lastY = mLastTouch.pointers[j].y;
2992 int32_t deltaY = abs(y - lastY);
2993
2994#if DEBUG_HACKS
2995 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2996 j, lastY, deltaY);
2997#endif
2998
2999 if (deltaY < maxDeltaY) {
3000 goto SkipSufficientlyClosePoint;
3001 }
3002 if (deltaY < closestDeltaY) {
3003 closestDeltaY = deltaY;
3004 closestY = lastY;
3005 }
3006 }
3007
3008 // Must not have found a close enough match.
3009#if DEBUG_HACKS
3010 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3011 i, y, closestY, closestDeltaY, maxDeltaY);
3012#endif
3013
3014 mCurrentTouch.pointers[i].y = closestY;
3015 return true; // XXX original code only corrects one point
3016
3017 SkipSufficientlyClosePoint: ;
3018 }
3019
3020 // No change.
3021 return false;
3022}
3023
3024/* Special hack for devices that have bad screen data: drop points where
3025 * the coordinate value for one axis has jumped to the other pointer's location.
3026 */
3027bool TouchInputMapper::applyJumpyTouchFilter() {
3028 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003029 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003030 return false;
3031 }
3032
3033 uint32_t pointerCount = mCurrentTouch.pointerCount;
3034 if (mLastTouch.pointerCount != pointerCount) {
3035#if DEBUG_HACKS
3036 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3037 mLastTouch.pointerCount, pointerCount);
3038 for (uint32_t i = 0; i < pointerCount; i++) {
3039 LOGD(" Pointer %d (%d, %d)", i,
3040 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3041 }
3042#endif
3043
3044 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3045 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3046 // Just drop the first few events going from 1 to 2 pointers.
3047 // They're bad often enough that they're not worth considering.
3048 mCurrentTouch.pointerCount = 1;
3049 mJumpyTouchFilter.jumpyPointsDropped += 1;
3050
3051#if DEBUG_HACKS
3052 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3053#endif
3054 return true;
3055 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3056 // The event when we go from 2 -> 1 tends to be messed up too
3057 mCurrentTouch.pointerCount = 2;
3058 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3059 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3060 mJumpyTouchFilter.jumpyPointsDropped += 1;
3061
3062#if DEBUG_HACKS
3063 for (int32_t i = 0; i < 2; i++) {
3064 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3065 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3066 }
3067#endif
3068 return true;
3069 }
3070 }
3071 // Reset jumpy points dropped on other transitions or if limit exceeded.
3072 mJumpyTouchFilter.jumpyPointsDropped = 0;
3073
3074#if DEBUG_HACKS
3075 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3076#endif
3077 return false;
3078 }
3079
3080 // We have the same number of pointers as last time.
3081 // A 'jumpy' point is one where the coordinate value for one axis
3082 // has jumped to the other pointer's location. No need to do anything
3083 // else if we only have one pointer.
3084 if (pointerCount < 2) {
3085 return false;
3086 }
3087
3088 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003089 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003090
3091 // We only replace the single worst jumpy point as characterized by pointer distance
3092 // in a single axis.
3093 int32_t badPointerIndex = -1;
3094 int32_t badPointerReplacementIndex = -1;
3095 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3096
3097 for (uint32_t i = pointerCount; i-- > 0; ) {
3098 int32_t x = mCurrentTouch.pointers[i].x;
3099 int32_t y = mCurrentTouch.pointers[i].y;
3100
3101#if DEBUG_HACKS
3102 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3103#endif
3104
3105 // Check if a touch point is too close to another's coordinates
3106 bool dropX = false, dropY = false;
3107 for (uint32_t j = 0; j < pointerCount; j++) {
3108 if (i == j) {
3109 continue;
3110 }
3111
3112 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3113 dropX = true;
3114 break;
3115 }
3116
3117 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3118 dropY = true;
3119 break;
3120 }
3121 }
3122 if (! dropX && ! dropY) {
3123 continue; // not jumpy
3124 }
3125
3126 // Find a replacement candidate by comparing with older points on the
3127 // complementary (non-jumpy) axis.
3128 int32_t distance = INT_MIN; // distance to be corrected
3129 int32_t replacementIndex = -1;
3130
3131 if (dropX) {
3132 // X looks too close. Find an older replacement point with a close Y.
3133 int32_t smallestDeltaY = INT_MAX;
3134 for (uint32_t j = 0; j < pointerCount; j++) {
3135 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3136 if (deltaY < smallestDeltaY) {
3137 smallestDeltaY = deltaY;
3138 replacementIndex = j;
3139 }
3140 }
3141 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3142 } else {
3143 // Y looks too close. Find an older replacement point with a close X.
3144 int32_t smallestDeltaX = INT_MAX;
3145 for (uint32_t j = 0; j < pointerCount; j++) {
3146 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3147 if (deltaX < smallestDeltaX) {
3148 smallestDeltaX = deltaX;
3149 replacementIndex = j;
3150 }
3151 }
3152 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3153 }
3154
3155 // If replacing this pointer would correct a worse error than the previous ones
3156 // considered, then use this replacement instead.
3157 if (distance > badPointerDistance) {
3158 badPointerIndex = i;
3159 badPointerReplacementIndex = replacementIndex;
3160 badPointerDistance = distance;
3161 }
3162 }
3163
3164 // Correct the jumpy pointer if one was found.
3165 if (badPointerIndex >= 0) {
3166#if DEBUG_HACKS
3167 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3168 badPointerIndex,
3169 mLastTouch.pointers[badPointerReplacementIndex].x,
3170 mLastTouch.pointers[badPointerReplacementIndex].y);
3171#endif
3172
3173 mCurrentTouch.pointers[badPointerIndex].x =
3174 mLastTouch.pointers[badPointerReplacementIndex].x;
3175 mCurrentTouch.pointers[badPointerIndex].y =
3176 mLastTouch.pointers[badPointerReplacementIndex].y;
3177 mJumpyTouchFilter.jumpyPointsDropped += 1;
3178 return true;
3179 }
3180 }
3181
3182 mJumpyTouchFilter.jumpyPointsDropped = 0;
3183 return false;
3184}
3185
3186/* Special hack for devices that have bad screen data: aggregate and
3187 * compute averages of the coordinate data, to reduce the amount of
3188 * jitter seen by applications. */
3189void TouchInputMapper::applyAveragingTouchFilter() {
3190 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3191 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3192 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3193 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003194 int32_t pressure;
3195 switch (mCalibration.pressureSource) {
3196 case Calibration::PRESSURE_SOURCE_PRESSURE:
3197 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3198 break;
3199 case Calibration::PRESSURE_SOURCE_TOUCH:
3200 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3201 break;
3202 default:
3203 pressure = 1;
3204 break;
3205 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003206
3207 if (mLastTouch.idBits.hasBit(id)) {
3208 // Pointer was down before and is still down now.
3209 // Compute average over history trace.
3210 uint32_t start = mAveragingTouchFilter.historyStart[id];
3211 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3212
3213 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3214 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3215 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3216
3217#if DEBUG_HACKS
3218 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3219 id, distance);
3220#endif
3221
3222 if (distance < AVERAGING_DISTANCE_LIMIT) {
3223 // Increment end index in preparation for recording new historical data.
3224 end += 1;
3225 if (end > AVERAGING_HISTORY_SIZE) {
3226 end = 0;
3227 }
3228
3229 // If the end index has looped back to the start index then we have filled
3230 // the historical trace up to the desired size so we drop the historical
3231 // data at the start of the trace.
3232 if (end == start) {
3233 start += 1;
3234 if (start > AVERAGING_HISTORY_SIZE) {
3235 start = 0;
3236 }
3237 }
3238
3239 // Add the raw data to the historical trace.
3240 mAveragingTouchFilter.historyStart[id] = start;
3241 mAveragingTouchFilter.historyEnd[id] = end;
3242 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3243 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3244 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3245
3246 // Average over all historical positions in the trace by total pressure.
3247 int32_t averagedX = 0;
3248 int32_t averagedY = 0;
3249 int32_t totalPressure = 0;
3250 for (;;) {
3251 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3252 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3253 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3254 .pointers[id].pressure;
3255
3256 averagedX += historicalX * historicalPressure;
3257 averagedY += historicalY * historicalPressure;
3258 totalPressure += historicalPressure;
3259
3260 if (start == end) {
3261 break;
3262 }
3263
3264 start += 1;
3265 if (start > AVERAGING_HISTORY_SIZE) {
3266 start = 0;
3267 }
3268 }
3269
Jeff Brown8d608662010-08-30 03:02:23 -07003270 if (totalPressure != 0) {
3271 averagedX /= totalPressure;
3272 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003273
3274#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003275 LOGD("AveragingTouchFilter: Pointer id %d - "
3276 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3277 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003278#endif
3279
Jeff Brown8d608662010-08-30 03:02:23 -07003280 mCurrentTouch.pointers[currentIndex].x = averagedX;
3281 mCurrentTouch.pointers[currentIndex].y = averagedY;
3282 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003283 } else {
3284#if DEBUG_HACKS
3285 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3286#endif
3287 }
3288 } else {
3289#if DEBUG_HACKS
3290 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3291#endif
3292 }
3293
3294 // Reset pointer history.
3295 mAveragingTouchFilter.historyStart[id] = 0;
3296 mAveragingTouchFilter.historyEnd[id] = 0;
3297 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3298 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3299 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3300 }
3301}
3302
3303int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003304 { // acquire lock
3305 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003306
Jeff Brown6328cdc2010-07-29 18:18:33 -07003307 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003308 return AKEY_STATE_VIRTUAL;
3309 }
3310
Jeff Brown6328cdc2010-07-29 18:18:33 -07003311 size_t numVirtualKeys = mLocked.virtualKeys.size();
3312 for (size_t i = 0; i < numVirtualKeys; i++) {
3313 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003314 if (virtualKey.keyCode == keyCode) {
3315 return AKEY_STATE_UP;
3316 }
3317 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003318 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003319
3320 return AKEY_STATE_UNKNOWN;
3321}
3322
3323int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003324 { // acquire lock
3325 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003326
Jeff Brown6328cdc2010-07-29 18:18:33 -07003327 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003328 return AKEY_STATE_VIRTUAL;
3329 }
3330
Jeff Brown6328cdc2010-07-29 18:18:33 -07003331 size_t numVirtualKeys = mLocked.virtualKeys.size();
3332 for (size_t i = 0; i < numVirtualKeys; i++) {
3333 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003334 if (virtualKey.scanCode == scanCode) {
3335 return AKEY_STATE_UP;
3336 }
3337 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003338 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003339
3340 return AKEY_STATE_UNKNOWN;
3341}
3342
3343bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3344 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003345 { // acquire lock
3346 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003347
Jeff Brown6328cdc2010-07-29 18:18:33 -07003348 size_t numVirtualKeys = mLocked.virtualKeys.size();
3349 for (size_t i = 0; i < numVirtualKeys; i++) {
3350 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003351
3352 for (size_t i = 0; i < numCodes; i++) {
3353 if (virtualKey.keyCode == keyCodes[i]) {
3354 outFlags[i] = 1;
3355 }
3356 }
3357 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003358 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003359
3360 return true;
3361}
3362
3363
3364// --- SingleTouchInputMapper ---
3365
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003366SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3367 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003368 initialize();
3369}
3370
3371SingleTouchInputMapper::~SingleTouchInputMapper() {
3372}
3373
3374void SingleTouchInputMapper::initialize() {
3375 mAccumulator.clear();
3376
3377 mDown = false;
3378 mX = 0;
3379 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003380 mPressure = 0; // default to 0 for devices that don't report pressure
3381 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003382}
3383
3384void SingleTouchInputMapper::reset() {
3385 TouchInputMapper::reset();
3386
Jeff Brown6d0fec22010-07-23 21:28:06 -07003387 initialize();
3388 }
3389
3390void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3391 switch (rawEvent->type) {
3392 case EV_KEY:
3393 switch (rawEvent->scanCode) {
3394 case BTN_TOUCH:
3395 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3396 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003397 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3398 // not have received valid position information yet. This logic assumes that
3399 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003400 break;
3401 }
3402 break;
3403
3404 case EV_ABS:
3405 switch (rawEvent->scanCode) {
3406 case ABS_X:
3407 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3408 mAccumulator.absX = rawEvent->value;
3409 break;
3410 case ABS_Y:
3411 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3412 mAccumulator.absY = rawEvent->value;
3413 break;
3414 case ABS_PRESSURE:
3415 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3416 mAccumulator.absPressure = rawEvent->value;
3417 break;
3418 case ABS_TOOL_WIDTH:
3419 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3420 mAccumulator.absToolWidth = rawEvent->value;
3421 break;
3422 }
3423 break;
3424
3425 case EV_SYN:
3426 switch (rawEvent->scanCode) {
3427 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003428 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003429 break;
3430 }
3431 break;
3432 }
3433}
3434
3435void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003436 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003437 if (fields == 0) {
3438 return; // no new state changes, so nothing to do
3439 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003440
3441 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3442 mDown = mAccumulator.btnTouch;
3443 }
3444
3445 if (fields & Accumulator::FIELD_ABS_X) {
3446 mX = mAccumulator.absX;
3447 }
3448
3449 if (fields & Accumulator::FIELD_ABS_Y) {
3450 mY = mAccumulator.absY;
3451 }
3452
3453 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3454 mPressure = mAccumulator.absPressure;
3455 }
3456
3457 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003458 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003459 }
3460
3461 mCurrentTouch.clear();
3462
3463 if (mDown) {
3464 mCurrentTouch.pointerCount = 1;
3465 mCurrentTouch.pointers[0].id = 0;
3466 mCurrentTouch.pointers[0].x = mX;
3467 mCurrentTouch.pointers[0].y = mY;
3468 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003469 mCurrentTouch.pointers[0].touchMajor = 0;
3470 mCurrentTouch.pointers[0].touchMinor = 0;
3471 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3472 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003473 mCurrentTouch.pointers[0].orientation = 0;
3474 mCurrentTouch.idToIndex[0] = 0;
3475 mCurrentTouch.idBits.markBit(0);
3476 }
3477
3478 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003479
3480 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003481}
3482
Jeff Brown8d608662010-08-30 03:02:23 -07003483void SingleTouchInputMapper::configureRawAxes() {
3484 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003485
Jeff Brown8d608662010-08-30 03:02:23 -07003486 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3487 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3488 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3489 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003490}
3491
3492
3493// --- MultiTouchInputMapper ---
3494
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003495MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3496 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003497 initialize();
3498}
3499
3500MultiTouchInputMapper::~MultiTouchInputMapper() {
3501}
3502
3503void MultiTouchInputMapper::initialize() {
3504 mAccumulator.clear();
3505}
3506
3507void MultiTouchInputMapper::reset() {
3508 TouchInputMapper::reset();
3509
Jeff Brown6d0fec22010-07-23 21:28:06 -07003510 initialize();
3511}
3512
3513void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3514 switch (rawEvent->type) {
3515 case EV_ABS: {
3516 uint32_t pointerIndex = mAccumulator.pointerCount;
3517 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3518
3519 switch (rawEvent->scanCode) {
3520 case ABS_MT_POSITION_X:
3521 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3522 pointer->absMTPositionX = rawEvent->value;
3523 break;
3524 case ABS_MT_POSITION_Y:
3525 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3526 pointer->absMTPositionY = rawEvent->value;
3527 break;
3528 case ABS_MT_TOUCH_MAJOR:
3529 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3530 pointer->absMTTouchMajor = rawEvent->value;
3531 break;
3532 case ABS_MT_TOUCH_MINOR:
3533 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3534 pointer->absMTTouchMinor = rawEvent->value;
3535 break;
3536 case ABS_MT_WIDTH_MAJOR:
3537 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3538 pointer->absMTWidthMajor = rawEvent->value;
3539 break;
3540 case ABS_MT_WIDTH_MINOR:
3541 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3542 pointer->absMTWidthMinor = rawEvent->value;
3543 break;
3544 case ABS_MT_ORIENTATION:
3545 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3546 pointer->absMTOrientation = rawEvent->value;
3547 break;
3548 case ABS_MT_TRACKING_ID:
3549 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3550 pointer->absMTTrackingId = rawEvent->value;
3551 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003552 case ABS_MT_PRESSURE:
3553 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3554 pointer->absMTPressure = rawEvent->value;
3555 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003556 }
3557 break;
3558 }
3559
3560 case EV_SYN:
3561 switch (rawEvent->scanCode) {
3562 case SYN_MT_REPORT: {
3563 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3564 uint32_t pointerIndex = mAccumulator.pointerCount;
3565
3566 if (mAccumulator.pointers[pointerIndex].fields) {
3567 if (pointerIndex == MAX_POINTERS) {
3568 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3569 MAX_POINTERS);
3570 } else {
3571 pointerIndex += 1;
3572 mAccumulator.pointerCount = pointerIndex;
3573 }
3574 }
3575
3576 mAccumulator.pointers[pointerIndex].clear();
3577 break;
3578 }
3579
3580 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003581 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003582 break;
3583 }
3584 break;
3585 }
3586}
3587
3588void MultiTouchInputMapper::sync(nsecs_t when) {
3589 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003590 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003591
Jeff Brown6d0fec22010-07-23 21:28:06 -07003592 uint32_t inCount = mAccumulator.pointerCount;
3593 uint32_t outCount = 0;
3594 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003595
Jeff Brown6d0fec22010-07-23 21:28:06 -07003596 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003597
Jeff Brown6d0fec22010-07-23 21:28:06 -07003598 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003599 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3600 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003601
Jeff Brown6d0fec22010-07-23 21:28:06 -07003602 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003603 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3604 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07003605 continue;
3606 }
3607
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003608 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3609 outPointer.x = inPointer.absMTPositionX;
3610 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003611
Jeff Brown8d608662010-08-30 03:02:23 -07003612 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3613 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003614 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3615 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003616 continue;
3617 }
Jeff Brown8d608662010-08-30 03:02:23 -07003618 outPointer.pressure = inPointer.absMTPressure;
3619 } else {
3620 // Default pressure to 0 if absent.
3621 outPointer.pressure = 0;
3622 }
3623
3624 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3625 if (inPointer.absMTTouchMajor <= 0) {
3626 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3627 // a pointer going up. Drop this finger.
3628 continue;
3629 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003630 outPointer.touchMajor = inPointer.absMTTouchMajor;
3631 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003632 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003633 outPointer.touchMajor = 0;
3634 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003635
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003636 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3637 outPointer.touchMinor = inPointer.absMTTouchMinor;
3638 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003639 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003640 outPointer.touchMinor = outPointer.touchMajor;
3641 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003642
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003643 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3644 outPointer.toolMajor = inPointer.absMTWidthMajor;
3645 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003646 // Default tool area to 0 if absent.
3647 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003648 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003649
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003650 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3651 outPointer.toolMinor = inPointer.absMTWidthMinor;
3652 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003653 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003654 outPointer.toolMinor = outPointer.toolMajor;
3655 }
3656
3657 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3658 outPointer.orientation = inPointer.absMTOrientation;
3659 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003660 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003661 outPointer.orientation = 0;
3662 }
3663
Jeff Brown8d608662010-08-30 03:02:23 -07003664 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003665 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003666 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3667 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003668
Jeff Brown6d0fec22010-07-23 21:28:06 -07003669 if (id > MAX_POINTER_ID) {
3670#if DEBUG_POINTERS
3671 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003672 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003673 id, MAX_POINTER_ID);
3674#endif
3675 havePointerIds = false;
3676 }
3677 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003678 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003679 mCurrentTouch.idToIndex[id] = outCount;
3680 mCurrentTouch.idBits.markBit(id);
3681 }
3682 } else {
3683 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003684 }
3685 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003686
Jeff Brown6d0fec22010-07-23 21:28:06 -07003687 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003688 }
3689
Jeff Brown6d0fec22010-07-23 21:28:06 -07003690 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003691
Jeff Brown6d0fec22010-07-23 21:28:06 -07003692 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003693
3694 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003695}
3696
Jeff Brown8d608662010-08-30 03:02:23 -07003697void MultiTouchInputMapper::configureRawAxes() {
3698 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003699
Jeff Brown8d608662010-08-30 03:02:23 -07003700 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3701 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3702 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3703 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3704 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3705 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3706 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3707 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003708}
3709
Jeff Brown46b9ac02010-04-22 18:58:52 -07003710
Jeff Browncb1404e2011-01-15 18:14:15 -08003711// --- JoystickInputMapper ---
3712
3713JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3714 InputMapper(device) {
3715 initialize();
3716}
3717
3718JoystickInputMapper::~JoystickInputMapper() {
3719}
3720
3721uint32_t JoystickInputMapper::getSources() {
3722 return AINPUT_SOURCE_JOYSTICK;
3723}
3724
3725void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3726 InputMapper::populateDeviceInfo(info);
3727
3728 if (mAxes.x.valid) {
3729 info->addMotionRange(AINPUT_MOTION_RANGE_X,
3730 mAxes.x.min, mAxes.x.max, mAxes.x.flat, mAxes.x.fuzz);
3731 }
3732 if (mAxes.y.valid) {
3733 info->addMotionRange(AINPUT_MOTION_RANGE_Y,
3734 mAxes.y.min, mAxes.y.max, mAxes.y.flat, mAxes.y.fuzz);
3735 }
3736}
3737
3738void JoystickInputMapper::dump(String8& dump) {
3739 dump.append(INDENT2 "Joystick Input Mapper:\n");
3740
3741 dump.append(INDENT3 "Raw Axes:\n");
3742 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
3743 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
3744
3745 dump.append(INDENT3 "Normalized Axes:\n");
3746 dumpNormalizedAxis(dump, mAxes.x, "X");
3747 dumpNormalizedAxis(dump, mAxes.y, "Y");
3748 dumpNormalizedAxis(dump, mAxes.hat0X, "Hat0X");
3749 dumpNormalizedAxis(dump, mAxes.hat0Y, "Hat0Y");
3750}
3751
3752void JoystickInputMapper::dumpNormalizedAxis(String8& dump,
3753 const NormalizedAxis& axis, const char* name) {
3754 if (axis.valid) {
3755 dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
3756 "scale=%0.3f, center=%0.3f, precision=%0.3f, value=%0.3f\n",
3757 name, axis.min, axis.max, axis.flat, axis.fuzz,
3758 axis.scale, axis.center, axis.precision, axis.value);
3759 } else {
3760 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
3761 }
3762}
3763
3764void JoystickInputMapper::configure() {
3765 InputMapper::configure();
3766
3767 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3768 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3769 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_HAT0X, & mRawAxes.hat0X);
3770 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_HAT0Y, & mRawAxes.hat0Y);
3771
3772 mAxes.x.configure(mRawAxes.x);
3773 mAxes.y.configure(mRawAxes.y);
3774 mAxes.hat0X.configure(mRawAxes.hat0X);
3775 mAxes.hat0Y.configure(mRawAxes.hat0Y);
3776}
3777
3778void JoystickInputMapper::initialize() {
3779 mAccumulator.clear();
3780
3781 mAxes.x.resetState();
3782 mAxes.y.resetState();
3783 mAxes.hat0X.resetState();
3784 mAxes.hat0Y.resetState();
3785}
3786
3787void JoystickInputMapper::reset() {
3788 // Recenter all axes.
3789 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
3790 mAccumulator.clear();
3791 mAccumulator.fields = Accumulator::FIELD_ALL;
3792 sync(when);
3793
3794 // Reinitialize state.
3795 initialize();
3796
3797 InputMapper::reset();
3798}
3799
3800void JoystickInputMapper::process(const RawEvent* rawEvent) {
3801 switch (rawEvent->type) {
3802 case EV_ABS:
3803 switch (rawEvent->scanCode) {
3804 case ABS_X:
3805 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3806 mAccumulator.absX = rawEvent->value;
3807 break;
3808 case ABS_Y:
3809 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3810 mAccumulator.absY = rawEvent->value;
3811 break;
3812 case ABS_HAT0X:
3813 mAccumulator.fields |= Accumulator::FIELD_ABS_HAT0X;
3814 mAccumulator.absHat0X = rawEvent->value;
3815 break;
3816 case ABS_HAT0Y:
3817 mAccumulator.fields |= Accumulator::FIELD_ABS_HAT0Y;
3818 mAccumulator.absHat0Y = rawEvent->value;
3819 break;
3820 }
3821 break;
3822
3823 case EV_SYN:
3824 switch (rawEvent->scanCode) {
3825 case SYN_REPORT:
3826 sync(rawEvent->when);
3827 break;
3828 }
3829 break;
3830 }
3831}
3832
3833void JoystickInputMapper::sync(nsecs_t when) {
3834 uint32_t fields = mAccumulator.fields;
3835 if (fields == 0) {
3836 return; // no new state changes, so nothing to do
3837 }
3838
3839 int32_t metaState = mContext->getGlobalMetaState();
3840
3841 bool motionAxisChanged = false;
3842 if (fields & Accumulator::FIELD_ABS_X) {
3843 if (mAxes.x.updateValue(mAccumulator.absX)) {
3844 motionAxisChanged = true;
3845 }
3846 }
3847
3848 if (fields & Accumulator::FIELD_ABS_Y) {
3849 if (mAxes.y.updateValue(mAccumulator.absY)) {
3850 motionAxisChanged = true;
3851 }
3852 }
3853
3854 if (motionAxisChanged) {
3855 PointerCoords pointerCoords;
3856 pointerCoords.x = mAxes.x.value;
3857 pointerCoords.y = mAxes.y.value;
3858 pointerCoords.touchMajor = 0;
3859 pointerCoords.touchMinor = 0;
3860 pointerCoords.toolMajor = 0;
3861 pointerCoords.toolMinor = 0;
3862 pointerCoords.pressure = 0;
3863 pointerCoords.size = 0;
3864 pointerCoords.orientation = 0;
3865
3866 int32_t pointerId = 0;
3867 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3868 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3869 1, &pointerId, &pointerCoords, mAxes.x.precision, mAxes.y.precision, 0);
3870 }
3871
3872 if (fields & Accumulator::FIELD_ABS_HAT0X) {
3873 if (mAxes.hat0X.updateValueAndDirection(mAccumulator.absHat0X)) {
3874 notifyDirectionalAxis(mAxes.hat0X, when, metaState,
3875 AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT);
3876 }
3877 }
3878
3879 if (fields & Accumulator::FIELD_ABS_HAT0Y) {
3880 if (mAxes.hat0Y.updateValueAndDirection(mAccumulator.absHat0Y)) {
3881 notifyDirectionalAxis(mAxes.hat0Y, when, metaState,
3882 AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN);
3883 }
3884 }
3885
3886 mAccumulator.clear();
3887}
3888
3889void JoystickInputMapper::notifyDirectionalAxis(DirectionalAxis& axis,
3890 nsecs_t when, int32_t metaState, int32_t lowKeyCode, int32_t highKeyCode) {
3891 if (axis.lastKeyCode) {
3892 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3893 AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM,
3894 axis.lastKeyCode, 0, metaState, when);
3895 axis.lastKeyCode = 0;
3896 }
3897 if (axis.direction) {
3898 axis.lastKeyCode = axis.direction > 0 ? highKeyCode : lowKeyCode;
3899 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3900 AKEY_EVENT_ACTION_DOWN, AKEY_EVENT_FLAG_FROM_SYSTEM,
3901 axis.lastKeyCode, 0, metaState, when);
3902 }
3903}
3904
3905
Jeff Brown46b9ac02010-04-22 18:58:52 -07003906} // namespace android