blob: c3c143c89c2d9437ec2e57026bab00074807811c [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 Brown05dc66a2011-03-02 14:41:58 -0800402void InputReader::fadePointer() {
403 { // acquire device registry reader lock
404 RWLock::AutoRLock _rl(mDeviceRegistryLock);
405
406 for (size_t i = 0; i < mDevices.size(); i++) {
407 InputDevice* device = mDevices.valueAt(i);
408 device->fadePointer();
409 }
410 } // release device registry reader lock
411}
412
Jeff Brown6d0fec22010-07-23 21:28:06 -0700413void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
414 { // acquire state lock
415 AutoMutex _l(mStateLock);
416
417 *outConfiguration = mInputConfiguration;
418 } // release state lock
419}
420
421status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
422 { // acquire device registry reader lock
423 RWLock::AutoRLock _rl(mDeviceRegistryLock);
424
425 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
426 if (deviceIndex < 0) {
427 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700428 }
429
Jeff Brown6d0fec22010-07-23 21:28:06 -0700430 InputDevice* device = mDevices.valueAt(deviceIndex);
431 if (device->isIgnored()) {
432 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700433 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700434
435 device->getDeviceInfo(outDeviceInfo);
436 return OK;
437 } // release device registy reader lock
438}
439
440void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
441 outDeviceIds.clear();
442
443 { // acquire device registry reader lock
444 RWLock::AutoRLock _rl(mDeviceRegistryLock);
445
446 size_t numDevices = mDevices.size();
447 for (size_t i = 0; i < numDevices; i++) {
448 InputDevice* device = mDevices.valueAt(i);
449 if (! device->isIgnored()) {
450 outDeviceIds.add(device->getId());
451 }
452 }
453 } // release device registy reader lock
454}
455
456int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
457 int32_t keyCode) {
458 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
459}
460
461int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
462 int32_t scanCode) {
463 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
464}
465
466int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
467 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
468}
469
470int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
471 GetStateFunc getStateFunc) {
472 { // acquire device registry reader lock
473 RWLock::AutoRLock _rl(mDeviceRegistryLock);
474
475 int32_t result = AKEY_STATE_UNKNOWN;
476 if (deviceId >= 0) {
477 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
478 if (deviceIndex >= 0) {
479 InputDevice* device = mDevices.valueAt(deviceIndex);
480 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
481 result = (device->*getStateFunc)(sourceMask, code);
482 }
483 }
484 } else {
485 size_t numDevices = mDevices.size();
486 for (size_t i = 0; i < numDevices; i++) {
487 InputDevice* device = mDevices.valueAt(i);
488 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
489 result = (device->*getStateFunc)(sourceMask, code);
490 if (result >= AKEY_STATE_DOWN) {
491 return result;
492 }
493 }
494 }
495 }
496 return result;
497 } // release device registy reader lock
498}
499
500bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
501 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
502 memset(outFlags, 0, numCodes);
503 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
504}
505
506bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
507 const int32_t* keyCodes, uint8_t* outFlags) {
508 { // acquire device registry reader lock
509 RWLock::AutoRLock _rl(mDeviceRegistryLock);
510 bool result = false;
511 if (deviceId >= 0) {
512 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
513 if (deviceIndex >= 0) {
514 InputDevice* device = mDevices.valueAt(deviceIndex);
515 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
516 result = device->markSupportedKeyCodes(sourceMask,
517 numCodes, keyCodes, outFlags);
518 }
519 }
520 } else {
521 size_t numDevices = mDevices.size();
522 for (size_t i = 0; i < numDevices; i++) {
523 InputDevice* device = mDevices.valueAt(i);
524 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
525 result |= device->markSupportedKeyCodes(sourceMask,
526 numCodes, keyCodes, outFlags);
527 }
528 }
529 }
530 return result;
531 } // release device registy reader lock
532}
533
Jeff Brownb88102f2010-09-08 11:49:43 -0700534void InputReader::dump(String8& dump) {
Jeff Brownf2f48712010-10-01 17:46:21 -0700535 mEventHub->dump(dump);
536 dump.append("\n");
537
538 dump.append("Input Reader State:\n");
539
Jeff Brownef3d7e82010-09-30 14:33:04 -0700540 { // acquire device registry reader lock
541 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700542
Jeff Brownef3d7e82010-09-30 14:33:04 -0700543 for (size_t i = 0; i < mDevices.size(); i++) {
544 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700545 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700546 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700547}
548
Jeff Brown6d0fec22010-07-23 21:28:06 -0700549
550// --- InputReaderThread ---
551
552InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
553 Thread(/*canCallJava*/ true), mReader(reader) {
554}
555
556InputReaderThread::~InputReaderThread() {
557}
558
559bool InputReaderThread::threadLoop() {
560 mReader->loopOnce();
561 return true;
562}
563
564
565// --- InputDevice ---
566
567InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
568 mContext(context), mId(id), mName(name), mSources(0) {
569}
570
571InputDevice::~InputDevice() {
572 size_t numMappers = mMappers.size();
573 for (size_t i = 0; i < numMappers; i++) {
574 delete mMappers[i];
575 }
576 mMappers.clear();
577}
578
Jeff Brownef3d7e82010-09-30 14:33:04 -0700579void InputDevice::dump(String8& dump) {
580 InputDeviceInfo deviceInfo;
581 getDeviceInfo(& deviceInfo);
582
Jeff Brown90655042010-12-02 13:50:46 -0800583 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700584 deviceInfo.getName().string());
585 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
586 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800587
588 const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges();
589 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700590 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800591 for (size_t i = 0; i < ranges.size(); i++) {
592 int32_t axis = ranges.keyAt(i);
593 const char* label = getAxisLabel(axis);
594 char name[32];
595 if (label) {
596 strncpy(name, label, sizeof(name));
597 name[sizeof(name) - 1] = '\0';
598 } else {
599 snprintf(name, sizeof(name), "%d", axis);
600 }
601 const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
602 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
603 name, range.min, range.max, range.flat, range.fuzz);
604 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700605 }
606
607 size_t numMappers = mMappers.size();
608 for (size_t i = 0; i < numMappers; i++) {
609 InputMapper* mapper = mMappers[i];
610 mapper->dump(dump);
611 }
612}
613
Jeff Brown6d0fec22010-07-23 21:28:06 -0700614void InputDevice::addMapper(InputMapper* mapper) {
615 mMappers.add(mapper);
616}
617
618void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700619 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800620 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700621 }
622
Jeff Brown6d0fec22010-07-23 21:28:06 -0700623 mSources = 0;
624
625 size_t numMappers = mMappers.size();
626 for (size_t i = 0; i < numMappers; i++) {
627 InputMapper* mapper = mMappers[i];
628 mapper->configure();
629 mSources |= mapper->getSources();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700630 }
631}
632
Jeff Brown6d0fec22010-07-23 21:28:06 -0700633void InputDevice::reset() {
634 size_t numMappers = mMappers.size();
635 for (size_t i = 0; i < numMappers; i++) {
636 InputMapper* mapper = mMappers[i];
637 mapper->reset();
638 }
639}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700640
Jeff Brown6d0fec22010-07-23 21:28:06 -0700641void InputDevice::process(const RawEvent* rawEvent) {
642 size_t numMappers = mMappers.size();
643 for (size_t i = 0; i < numMappers; i++) {
644 InputMapper* mapper = mMappers[i];
645 mapper->process(rawEvent);
646 }
647}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700648
Jeff Brown6d0fec22010-07-23 21:28:06 -0700649void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
650 outDeviceInfo->initialize(mId, mName);
651
652 size_t numMappers = mMappers.size();
653 for (size_t i = 0; i < numMappers; i++) {
654 InputMapper* mapper = mMappers[i];
655 mapper->populateDeviceInfo(outDeviceInfo);
656 }
657}
658
659int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
660 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
661}
662
663int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
664 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
665}
666
667int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
668 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
669}
670
671int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
672 int32_t result = AKEY_STATE_UNKNOWN;
673 size_t numMappers = mMappers.size();
674 for (size_t i = 0; i < numMappers; i++) {
675 InputMapper* mapper = mMappers[i];
676 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
677 result = (mapper->*getStateFunc)(sourceMask, code);
678 if (result >= AKEY_STATE_DOWN) {
679 return result;
680 }
681 }
682 }
683 return result;
684}
685
686bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
687 const int32_t* keyCodes, uint8_t* outFlags) {
688 bool result = false;
689 size_t numMappers = mMappers.size();
690 for (size_t i = 0; i < numMappers; i++) {
691 InputMapper* mapper = mMappers[i];
692 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
693 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
694 }
695 }
696 return result;
697}
698
699int32_t InputDevice::getMetaState() {
700 int32_t result = 0;
701 size_t numMappers = mMappers.size();
702 for (size_t i = 0; i < numMappers; i++) {
703 InputMapper* mapper = mMappers[i];
704 result |= mapper->getMetaState();
705 }
706 return result;
707}
708
Jeff Brown05dc66a2011-03-02 14:41:58 -0800709void InputDevice::fadePointer() {
710 size_t numMappers = mMappers.size();
711 for (size_t i = 0; i < numMappers; i++) {
712 InputMapper* mapper = mMappers[i];
713 mapper->fadePointer();
714 }
715}
716
Jeff Brown6d0fec22010-07-23 21:28:06 -0700717
718// --- InputMapper ---
719
720InputMapper::InputMapper(InputDevice* device) :
721 mDevice(device), mContext(device->getContext()) {
722}
723
724InputMapper::~InputMapper() {
725}
726
727void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
728 info->addSource(getSources());
729}
730
Jeff Brownef3d7e82010-09-30 14:33:04 -0700731void InputMapper::dump(String8& dump) {
732}
733
Jeff Brown6d0fec22010-07-23 21:28:06 -0700734void InputMapper::configure() {
735}
736
737void InputMapper::reset() {
738}
739
740int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
741 return AKEY_STATE_UNKNOWN;
742}
743
744int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
745 return AKEY_STATE_UNKNOWN;
746}
747
748int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
749 return AKEY_STATE_UNKNOWN;
750}
751
752bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
753 const int32_t* keyCodes, uint8_t* outFlags) {
754 return false;
755}
756
757int32_t InputMapper::getMetaState() {
758 return 0;
759}
760
Jeff Brown05dc66a2011-03-02 14:41:58 -0800761void InputMapper::fadePointer() {
762}
763
Jeff Browncb1404e2011-01-15 18:14:15 -0800764void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
765 const RawAbsoluteAxisInfo& axis, const char* name) {
766 if (axis.valid) {
767 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
768 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
769 } else {
770 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
771 }
772}
773
Jeff Brown6d0fec22010-07-23 21:28:06 -0700774
775// --- SwitchInputMapper ---
776
777SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
778 InputMapper(device) {
779}
780
781SwitchInputMapper::~SwitchInputMapper() {
782}
783
784uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800785 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700786}
787
788void SwitchInputMapper::process(const RawEvent* rawEvent) {
789 switch (rawEvent->type) {
790 case EV_SW:
791 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
792 break;
793 }
794}
795
796void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700797 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700798}
799
800int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
801 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
802}
803
804
805// --- KeyboardInputMapper ---
806
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800807KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700808 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800809 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700810 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700811 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700812}
813
814KeyboardInputMapper::~KeyboardInputMapper() {
815}
816
Jeff Brown6328cdc2010-07-29 18:18:33 -0700817void KeyboardInputMapper::initializeLocked() {
818 mLocked.metaState = AMETA_NONE;
819 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700820}
821
822uint32_t KeyboardInputMapper::getSources() {
823 return mSources;
824}
825
826void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
827 InputMapper::populateDeviceInfo(info);
828
829 info->setKeyboardType(mKeyboardType);
830}
831
Jeff Brownef3d7e82010-09-30 14:33:04 -0700832void KeyboardInputMapper::dump(String8& dump) {
833 { // acquire lock
834 AutoMutex _l(mLock);
835 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800836 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700837 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
838 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
839 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
840 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
841 } // release lock
842}
843
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800844
845void KeyboardInputMapper::configure() {
846 InputMapper::configure();
847
848 // Configure basic parameters.
849 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800850
851 // Reset LEDs.
852 {
853 AutoMutex _l(mLock);
854 resetLedStateLocked();
855 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800856}
857
858void KeyboardInputMapper::configureParameters() {
859 mParameters.orientationAware = false;
860 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
861 mParameters.orientationAware);
862
863 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
864}
865
866void KeyboardInputMapper::dumpParameters(String8& dump) {
867 dump.append(INDENT3 "Parameters:\n");
868 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
869 mParameters.associatedDisplayId);
870 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
871 toString(mParameters.orientationAware));
872}
873
Jeff Brown6d0fec22010-07-23 21:28:06 -0700874void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700875 for (;;) {
876 int32_t keyCode, scanCode;
877 { // acquire lock
878 AutoMutex _l(mLock);
879
880 // Synthesize key up event on reset if keys are currently down.
881 if (mLocked.keyDowns.isEmpty()) {
882 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800883 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700884 break; // done
885 }
886
887 const KeyDown& keyDown = mLocked.keyDowns.top();
888 keyCode = keyDown.keyCode;
889 scanCode = keyDown.scanCode;
890 } // release lock
891
Jeff Brown6d0fec22010-07-23 21:28:06 -0700892 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700893 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700894 }
895
896 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700897 getContext()->updateGlobalMetaState();
898}
899
900void KeyboardInputMapper::process(const RawEvent* rawEvent) {
901 switch (rawEvent->type) {
902 case EV_KEY: {
903 int32_t scanCode = rawEvent->scanCode;
904 if (isKeyboardOrGamepadKey(scanCode)) {
905 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
906 rawEvent->flags);
907 }
908 break;
909 }
910 }
911}
912
913bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
914 return scanCode < BTN_MOUSE
915 || scanCode >= KEY_OK
Jeff Browncb1404e2011-01-15 18:14:15 -0800916 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700917}
918
Jeff Brown6328cdc2010-07-29 18:18:33 -0700919void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
920 int32_t scanCode, uint32_t policyFlags) {
921 int32_t newMetaState;
922 nsecs_t downTime;
923 bool metaStateChanged = false;
924
925 { // acquire lock
926 AutoMutex _l(mLock);
927
928 if (down) {
929 // Rotate key codes according to orientation if needed.
930 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800931 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700932 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800933 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
934 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800935 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700936 }
937
938 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700939 }
940
Jeff Brown6328cdc2010-07-29 18:18:33 -0700941 // Add key down.
942 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
943 if (keyDownIndex >= 0) {
944 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800945 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700946 } else {
947 // key down
Jeff Brownfe508922011-01-18 15:10:10 -0800948 if ((policyFlags & POLICY_FLAG_VIRTUAL)
949 && mContext->shouldDropVirtualKey(when,
950 getDevice(), keyCode, scanCode)) {
951 return;
952 }
953
Jeff Brown6328cdc2010-07-29 18:18:33 -0700954 mLocked.keyDowns.push();
955 KeyDown& keyDown = mLocked.keyDowns.editTop();
956 keyDown.keyCode = keyCode;
957 keyDown.scanCode = scanCode;
958 }
959
960 mLocked.downTime = when;
961 } else {
962 // Remove key down.
963 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
964 if (keyDownIndex >= 0) {
965 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800966 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700967 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
968 } else {
969 // key was not actually down
970 LOGI("Dropping key up from device %s because the key was not down. "
971 "keyCode=%d, scanCode=%d",
972 getDeviceName().string(), keyCode, scanCode);
973 return;
974 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700975 }
976
Jeff Brown6328cdc2010-07-29 18:18:33 -0700977 int32_t oldMetaState = mLocked.metaState;
978 newMetaState = updateMetaState(keyCode, down, oldMetaState);
979 if (oldMetaState != newMetaState) {
980 mLocked.metaState = newMetaState;
981 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -0700982 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700983 }
Jeff Brownfd035822010-06-30 16:10:35 -0700984
Jeff Brown6328cdc2010-07-29 18:18:33 -0700985 downTime = mLocked.downTime;
986 } // release lock
987
988 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700989 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700990 }
991
Jeff Brown05dc66a2011-03-02 14:41:58 -0800992 if (down && !isMetaKey(keyCode)) {
993 getContext()->fadePointer();
994 }
995
Jeff Brown497a92c2010-09-12 17:55:08 -0700996 if (policyFlags & POLICY_FLAG_FUNCTION) {
997 newMetaState |= AMETA_FUNCTION_ON;
998 }
Jeff Brown83c09682010-12-23 17:50:18 -0800999 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001000 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1001 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001002}
1003
Jeff Brown6328cdc2010-07-29 18:18:33 -07001004ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1005 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001006 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001007 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001008 return i;
1009 }
1010 }
1011 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001012}
1013
Jeff Brown6d0fec22010-07-23 21:28:06 -07001014int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1015 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1016}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001017
Jeff Brown6d0fec22010-07-23 21:28:06 -07001018int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1019 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1020}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001021
Jeff Brown6d0fec22010-07-23 21:28:06 -07001022bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1023 const int32_t* keyCodes, uint8_t* outFlags) {
1024 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1025}
1026
1027int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001028 { // acquire lock
1029 AutoMutex _l(mLock);
1030 return mLocked.metaState;
1031 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001032}
1033
Jeff Brown49ed71d2010-12-06 17:13:33 -08001034void KeyboardInputMapper::resetLedStateLocked() {
1035 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1036 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1037 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1038
1039 updateLedStateLocked(true);
1040}
1041
1042void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1043 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1044 ledState.on = false;
1045}
1046
Jeff Brown497a92c2010-09-12 17:55:08 -07001047void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1048 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001049 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001050 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001051 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001052 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001053 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001054}
1055
1056void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1057 int32_t led, int32_t modifier, bool reset) {
1058 if (ledState.avail) {
1059 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001060 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001061 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1062 ledState.on = desiredState;
1063 }
1064 }
1065}
1066
Jeff Brown6d0fec22010-07-23 21:28:06 -07001067
Jeff Brown83c09682010-12-23 17:50:18 -08001068// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001069
Jeff Brown83c09682010-12-23 17:50:18 -08001070CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001071 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001072 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001073}
1074
Jeff Brown83c09682010-12-23 17:50:18 -08001075CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001076}
1077
Jeff Brown83c09682010-12-23 17:50:18 -08001078uint32_t CursorInputMapper::getSources() {
1079 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001080}
1081
Jeff Brown83c09682010-12-23 17:50:18 -08001082void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001083 InputMapper::populateDeviceInfo(info);
1084
Jeff Brown83c09682010-12-23 17:50:18 -08001085 if (mParameters.mode == Parameters::MODE_POINTER) {
1086 float minX, minY, maxX, maxY;
1087 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001088 info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
1089 info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001090 }
1091 } else {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001092 info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
1093 info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001094 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001095 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
1096
1097 if (mHaveVWheel) {
1098 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1099 }
1100 if (mHaveHWheel) {
1101 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1102 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001103}
1104
Jeff Brown83c09682010-12-23 17:50:18 -08001105void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001106 { // acquire lock
1107 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001108 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001109 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001110 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1111 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001112 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1113 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001114 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1115 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1116 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1117 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001118 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1119 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1120 } // release lock
1121}
1122
Jeff Brown83c09682010-12-23 17:50:18 -08001123void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001124 InputMapper::configure();
1125
1126 // Configure basic parameters.
1127 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001128
1129 // Configure device mode.
1130 switch (mParameters.mode) {
1131 case Parameters::MODE_POINTER:
1132 mSources = AINPUT_SOURCE_MOUSE;
1133 mXPrecision = 1.0f;
1134 mYPrecision = 1.0f;
1135 mXScale = 1.0f;
1136 mYScale = 1.0f;
1137 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1138 break;
1139 case Parameters::MODE_NAVIGATION:
1140 mSources = AINPUT_SOURCE_TRACKBALL;
1141 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1142 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1143 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1144 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1145 break;
1146 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001147
1148 mVWheelScale = 1.0f;
1149 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001150
1151 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1152 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001153}
1154
Jeff Brown83c09682010-12-23 17:50:18 -08001155void CursorInputMapper::configureParameters() {
1156 mParameters.mode = Parameters::MODE_POINTER;
1157 String8 cursorModeString;
1158 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1159 if (cursorModeString == "navigation") {
1160 mParameters.mode = Parameters::MODE_NAVIGATION;
1161 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1162 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1163 }
1164 }
1165
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001166 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001167 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001168 mParameters.orientationAware);
1169
Jeff Brown83c09682010-12-23 17:50:18 -08001170 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1171 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001172}
1173
Jeff Brown83c09682010-12-23 17:50:18 -08001174void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001175 dump.append(INDENT3 "Parameters:\n");
1176 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1177 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001178
1179 switch (mParameters.mode) {
1180 case Parameters::MODE_POINTER:
1181 dump.append(INDENT4 "Mode: pointer\n");
1182 break;
1183 case Parameters::MODE_NAVIGATION:
1184 dump.append(INDENT4 "Mode: navigation\n");
1185 break;
1186 default:
1187 assert(false);
1188 }
1189
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001190 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1191 toString(mParameters.orientationAware));
1192}
1193
Jeff Brown83c09682010-12-23 17:50:18 -08001194void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001195 mAccumulator.clear();
1196
Jeff Brown6328cdc2010-07-29 18:18:33 -07001197 mLocked.down = false;
1198 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001199}
1200
Jeff Brown83c09682010-12-23 17:50:18 -08001201void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001202 for (;;) {
1203 { // acquire lock
1204 AutoMutex _l(mLock);
1205
1206 if (! mLocked.down) {
1207 initializeLocked();
1208 break; // done
1209 }
1210 } // release lock
1211
Jeff Brown83c09682010-12-23 17:50:18 -08001212 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001213 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001214 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001215 mAccumulator.btnMouse = false;
1216 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001217 }
1218
Jeff Brown6d0fec22010-07-23 21:28:06 -07001219 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001220}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001221
Jeff Brown83c09682010-12-23 17:50:18 -08001222void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001223 switch (rawEvent->type) {
1224 case EV_KEY:
1225 switch (rawEvent->scanCode) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001226 case BTN_LEFT:
1227 case BTN_RIGHT:
1228 case BTN_MIDDLE:
1229 case BTN_SIDE:
1230 case BTN_EXTRA:
1231 case BTN_FORWARD:
1232 case BTN_BACK:
1233 case BTN_TASK:
Jeff Brown6d0fec22010-07-23 21:28:06 -07001234 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1235 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001236 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1237 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001238 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001239 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001240 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001241 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001242
Jeff Brown6d0fec22010-07-23 21:28:06 -07001243 case EV_REL:
1244 switch (rawEvent->scanCode) {
1245 case REL_X:
1246 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1247 mAccumulator.relX = rawEvent->value;
1248 break;
1249 case REL_Y:
1250 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1251 mAccumulator.relY = rawEvent->value;
1252 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001253 case REL_WHEEL:
1254 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1255 mAccumulator.relWheel = rawEvent->value;
1256 break;
1257 case REL_HWHEEL:
1258 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1259 mAccumulator.relHWheel = rawEvent->value;
1260 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001261 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001262 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001263
Jeff Brown6d0fec22010-07-23 21:28:06 -07001264 case EV_SYN:
1265 switch (rawEvent->scanCode) {
1266 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001267 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001268 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001269 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001270 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001271 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001272}
1273
Jeff Brown83c09682010-12-23 17:50:18 -08001274void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001275 uint32_t fields = mAccumulator.fields;
1276 if (fields == 0) {
1277 return; // no new state changes, so nothing to do
1278 }
1279
Jeff Brown6328cdc2010-07-29 18:18:33 -07001280 int motionEventAction;
1281 PointerCoords pointerCoords;
1282 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001283 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001284 { // acquire lock
1285 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001286
Jeff Brown6328cdc2010-07-29 18:18:33 -07001287 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1288
1289 if (downChanged) {
1290 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001291 if (!mLocked.down) {
1292 mLocked.down = true;
1293 mLocked.downTime = when;
1294 } else {
1295 downChanged = false;
1296 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001297 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001298 if (mLocked.down) {
1299 mLocked.down = false;
1300 } else {
1301 downChanged = false;
1302 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001303 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001304 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001305
Jeff Brown6328cdc2010-07-29 18:18:33 -07001306 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001307 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1308 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001309
Jeff Brown6328cdc2010-07-29 18:18:33 -07001310 if (downChanged) {
1311 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browncc0c1592011-02-19 05:07:28 -08001312 } else if (mLocked.down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001313 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001314 } else {
1315 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001316 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001317
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001318 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001319 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001320 // Rotate motion based on display orientation if needed.
1321 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1322 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001323 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1324 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001325 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001326 }
1327
1328 float temp;
1329 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001330 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001331 temp = deltaX;
1332 deltaX = deltaY;
1333 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001334 break;
1335
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001336 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001337 deltaX = -deltaX;
1338 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001339 break;
1340
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001341 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001342 temp = deltaX;
1343 deltaX = -deltaY;
1344 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001345 break;
1346 }
1347 }
Jeff Brown83c09682010-12-23 17:50:18 -08001348
Jeff Brown91c69ab2011-02-14 17:03:18 -08001349 pointerCoords.clear();
1350
Jeff Brown83c09682010-12-23 17:50:18 -08001351 if (mPointerController != NULL) {
1352 mPointerController->move(deltaX, deltaY);
1353 if (downChanged) {
1354 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1355 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08001356 float x, y;
1357 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001358 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1359 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown83c09682010-12-23 17:50:18 -08001360 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001361 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1362 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001363 }
1364
Jeff Brownebbd5d12011-02-17 13:01:34 -08001365 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001366
1367 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001368 vscroll = mAccumulator.relWheel;
1369 } else {
1370 vscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001371 }
1372 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001373 hscroll = mAccumulator.relHWheel;
1374 } else {
1375 hscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001376 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001377 if (hscroll != 0 || vscroll != 0) {
1378 mPointerController->unfade();
1379 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001380 } // release lock
1381
Jeff Brown6d0fec22010-07-23 21:28:06 -07001382 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001383 int32_t pointerId = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001384 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
Jeff Brown85a31762010-09-01 17:01:00 -07001385 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001386 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1387
1388 mAccumulator.clear();
Jeff Brown33bbfd22011-02-24 20:55:35 -08001389
1390 if (vscroll != 0 || hscroll != 0) {
1391 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1392 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1393
1394 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
1395 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1396 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1397 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001398}
1399
Jeff Brown83c09682010-12-23 17:50:18 -08001400int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001401 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1402 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1403 } else {
1404 return AKEY_STATE_UNKNOWN;
1405 }
1406}
1407
Jeff Brown05dc66a2011-03-02 14:41:58 -08001408void CursorInputMapper::fadePointer() {
1409 { // acquire lock
1410 AutoMutex _l(mLock);
1411 mPointerController->fade();
1412 } // release lock
1413}
1414
Jeff Brown6d0fec22010-07-23 21:28:06 -07001415
1416// --- TouchInputMapper ---
1417
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001418TouchInputMapper::TouchInputMapper(InputDevice* device) :
1419 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001420 mLocked.surfaceOrientation = -1;
1421 mLocked.surfaceWidth = -1;
1422 mLocked.surfaceHeight = -1;
1423
1424 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001425}
1426
1427TouchInputMapper::~TouchInputMapper() {
1428}
1429
1430uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001431 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001432}
1433
1434void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1435 InputMapper::populateDeviceInfo(info);
1436
Jeff Brown6328cdc2010-07-29 18:18:33 -07001437 { // acquire lock
1438 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001439
Jeff Brown6328cdc2010-07-29 18:18:33 -07001440 // Ensure surface information is up to date so that orientation changes are
1441 // noticed immediately.
1442 configureSurfaceLocked();
1443
Jeff Brown6f2fba42011-02-19 01:08:02 -08001444 info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1445 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001446
1447 if (mLocked.orientedRanges.havePressure) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001448 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown8d608662010-08-30 03:02:23 -07001449 mLocked.orientedRanges.pressure);
1450 }
1451
1452 if (mLocked.orientedRanges.haveSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001453 info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown8d608662010-08-30 03:02:23 -07001454 mLocked.orientedRanges.size);
1455 }
1456
Jeff Brownc6d282b2010-10-14 21:42:15 -07001457 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001458 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001459 mLocked.orientedRanges.touchMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001460 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001461 mLocked.orientedRanges.touchMinor);
1462 }
1463
Jeff Brownc6d282b2010-10-14 21:42:15 -07001464 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001465 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001466 mLocked.orientedRanges.toolMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001467 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001468 mLocked.orientedRanges.toolMinor);
1469 }
1470
1471 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001472 info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown8d608662010-08-30 03:02:23 -07001473 mLocked.orientedRanges.orientation);
1474 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001475 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001476}
1477
Jeff Brownef3d7e82010-09-30 14:33:04 -07001478void TouchInputMapper::dump(String8& dump) {
1479 { // acquire lock
1480 AutoMutex _l(mLock);
1481 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001482 dumpParameters(dump);
1483 dumpVirtualKeysLocked(dump);
1484 dumpRawAxes(dump);
1485 dumpCalibration(dump);
1486 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001487 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001488 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1489 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1490 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1491 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1492 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1493 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1494 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1495 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1496 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1497 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1498 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1499 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1500 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1501 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001502 } // release lock
1503}
1504
Jeff Brown6328cdc2010-07-29 18:18:33 -07001505void TouchInputMapper::initializeLocked() {
1506 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001507 mLastTouch.clear();
1508 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001509
1510 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1511 mAveragingTouchFilter.historyStart[i] = 0;
1512 mAveragingTouchFilter.historyEnd[i] = 0;
1513 }
1514
1515 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001516
1517 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001518
1519 mLocked.orientedRanges.havePressure = false;
1520 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001521 mLocked.orientedRanges.haveTouchSize = false;
1522 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001523 mLocked.orientedRanges.haveOrientation = false;
1524}
1525
Jeff Brown6d0fec22010-07-23 21:28:06 -07001526void TouchInputMapper::configure() {
1527 InputMapper::configure();
1528
1529 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001530 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001531
Jeff Brown83c09682010-12-23 17:50:18 -08001532 // Configure sources.
1533 switch (mParameters.deviceType) {
1534 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1535 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1536 break;
1537 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1538 mSources = AINPUT_SOURCE_TOUCHPAD;
1539 break;
1540 default:
1541 assert(false);
1542 }
1543
Jeff Brown6d0fec22010-07-23 21:28:06 -07001544 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001545 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001546
1547 // Prepare input device calibration.
1548 parseCalibration();
1549 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001550
Jeff Brown6328cdc2010-07-29 18:18:33 -07001551 { // acquire lock
1552 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001553
Jeff Brown8d608662010-08-30 03:02:23 -07001554 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001555 configureSurfaceLocked();
1556 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001557}
1558
Jeff Brown8d608662010-08-30 03:02:23 -07001559void TouchInputMapper::configureParameters() {
1560 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1561 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1562 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001563 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001564
1565 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001566 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001567 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1568 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001569 if (deviceTypeString == "touchScreen") {
1570 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1571 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001572 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1573 }
1574 }
1575 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1576
1577 mParameters.orientationAware = isTouchScreen;
1578 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1579 mParameters.orientationAware);
1580
1581 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001582}
1583
Jeff Brownef3d7e82010-09-30 14:33:04 -07001584void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001585 dump.append(INDENT3 "Parameters:\n");
1586
1587 switch (mParameters.deviceType) {
1588 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1589 dump.append(INDENT4 "DeviceType: touchScreen\n");
1590 break;
1591 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1592 dump.append(INDENT4 "DeviceType: touchPad\n");
1593 break;
1594 default:
1595 assert(false);
1596 }
1597
1598 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1599 mParameters.associatedDisplayId);
1600 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1601 toString(mParameters.orientationAware));
1602
1603 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001604 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001605 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001606 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001607 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001608 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001609}
1610
Jeff Brown8d608662010-08-30 03:02:23 -07001611void TouchInputMapper::configureRawAxes() {
1612 mRawAxes.x.clear();
1613 mRawAxes.y.clear();
1614 mRawAxes.pressure.clear();
1615 mRawAxes.touchMajor.clear();
1616 mRawAxes.touchMinor.clear();
1617 mRawAxes.toolMajor.clear();
1618 mRawAxes.toolMinor.clear();
1619 mRawAxes.orientation.clear();
1620}
1621
Jeff Brownef3d7e82010-09-30 14:33:04 -07001622void TouchInputMapper::dumpRawAxes(String8& dump) {
1623 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001624 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1625 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1626 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1627 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1628 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1629 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1630 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1631 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001632}
1633
Jeff Brown6328cdc2010-07-29 18:18:33 -07001634bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001635 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001636 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001637 int32_t width = mRawAxes.x.getRange();
1638 int32_t height = mRawAxes.y.getRange();
1639
1640 if (mParameters.associatedDisplayId >= 0) {
1641 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1642 bool wantOrientation = mParameters.orientationAware;
1643
Jeff Brown6328cdc2010-07-29 18:18:33 -07001644 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001645 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1646 wantSize ? &width : NULL, wantSize ? &height : NULL,
1647 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001648 return false;
1649 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001650 }
1651
Jeff Brown6328cdc2010-07-29 18:18:33 -07001652 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001653 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001654 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001655 }
1656
Jeff Brown6328cdc2010-07-29 18:18:33 -07001657 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001658 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001659 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001660 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001661
Jeff Brown6328cdc2010-07-29 18:18:33 -07001662 mLocked.surfaceWidth = width;
1663 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001664
Jeff Brown8d608662010-08-30 03:02:23 -07001665 // Configure X and Y factors.
1666 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001667 mLocked.xOrigin = mCalibration.haveXOrigin
1668 ? mCalibration.xOrigin
1669 : mRawAxes.x.minValue;
1670 mLocked.yOrigin = mCalibration.haveYOrigin
1671 ? mCalibration.yOrigin
1672 : mRawAxes.y.minValue;
1673 mLocked.xScale = mCalibration.haveXScale
1674 ? mCalibration.xScale
1675 : float(width) / mRawAxes.x.getRange();
1676 mLocked.yScale = mCalibration.haveYScale
1677 ? mCalibration.yScale
1678 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001679 mLocked.xPrecision = 1.0f / mLocked.xScale;
1680 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001681
Jeff Brown6328cdc2010-07-29 18:18:33 -07001682 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001683 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001684 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001685 mLocked.xOrigin = 0;
1686 mLocked.yOrigin = 0;
1687 mLocked.xScale = 1.0f;
1688 mLocked.yScale = 1.0f;
1689 mLocked.xPrecision = 1.0f;
1690 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001691 }
1692
Jeff Brown8d608662010-08-30 03:02:23 -07001693 // Scale factor for terms that are not oriented in a particular axis.
1694 // If the pixels are square then xScale == yScale otherwise we fake it
1695 // by choosing an average.
1696 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001697
Jeff Brown8d608662010-08-30 03:02:23 -07001698 // Size of diagonal axis.
1699 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001700
Jeff Brown8d608662010-08-30 03:02:23 -07001701 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001702 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1703 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001704 mLocked.orientedRanges.touchMajor.min = 0;
1705 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1706 mLocked.orientedRanges.touchMajor.flat = 0;
1707 mLocked.orientedRanges.touchMajor.fuzz = 0;
1708 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1709 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001710
Jeff Brown8d608662010-08-30 03:02:23 -07001711 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001712 mLocked.toolSizeLinearScale = 0;
1713 mLocked.toolSizeLinearBias = 0;
1714 mLocked.toolSizeAreaScale = 0;
1715 mLocked.toolSizeAreaBias = 0;
1716 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1717 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1718 if (mCalibration.haveToolSizeLinearScale) {
1719 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001720 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001721 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001722 / mRawAxes.toolMajor.maxValue;
1723 }
1724
Jeff Brownc6d282b2010-10-14 21:42:15 -07001725 if (mCalibration.haveToolSizeLinearBias) {
1726 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1727 }
1728 } else if (mCalibration.toolSizeCalibration ==
1729 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1730 if (mCalibration.haveToolSizeLinearScale) {
1731 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1732 } else {
1733 mLocked.toolSizeLinearScale = min(width, height);
1734 }
1735
1736 if (mCalibration.haveToolSizeLinearBias) {
1737 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1738 }
1739
1740 if (mCalibration.haveToolSizeAreaScale) {
1741 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1742 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1743 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1744 }
1745
1746 if (mCalibration.haveToolSizeAreaBias) {
1747 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001748 }
1749 }
1750
Jeff Brownc6d282b2010-10-14 21:42:15 -07001751 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001752 mLocked.orientedRanges.toolMajor.min = 0;
1753 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1754 mLocked.orientedRanges.toolMajor.flat = 0;
1755 mLocked.orientedRanges.toolMajor.fuzz = 0;
1756 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1757 }
1758
1759 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001760 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001761 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1762 RawAbsoluteAxisInfo rawPressureAxis;
1763 switch (mCalibration.pressureSource) {
1764 case Calibration::PRESSURE_SOURCE_PRESSURE:
1765 rawPressureAxis = mRawAxes.pressure;
1766 break;
1767 case Calibration::PRESSURE_SOURCE_TOUCH:
1768 rawPressureAxis = mRawAxes.touchMajor;
1769 break;
1770 default:
1771 rawPressureAxis.clear();
1772 }
1773
Jeff Brown8d608662010-08-30 03:02:23 -07001774 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1775 || mCalibration.pressureCalibration
1776 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1777 if (mCalibration.havePressureScale) {
1778 mLocked.pressureScale = mCalibration.pressureScale;
1779 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1780 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1781 }
1782 }
1783
1784 mLocked.orientedRanges.havePressure = true;
1785 mLocked.orientedRanges.pressure.min = 0;
1786 mLocked.orientedRanges.pressure.max = 1.0;
1787 mLocked.orientedRanges.pressure.flat = 0;
1788 mLocked.orientedRanges.pressure.fuzz = 0;
1789 }
1790
1791 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001792 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001793 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001794 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1795 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1796 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1797 }
1798 }
1799
1800 mLocked.orientedRanges.haveSize = true;
1801 mLocked.orientedRanges.size.min = 0;
1802 mLocked.orientedRanges.size.max = 1.0;
1803 mLocked.orientedRanges.size.flat = 0;
1804 mLocked.orientedRanges.size.fuzz = 0;
1805 }
1806
1807 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001808 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001809 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001810 if (mCalibration.orientationCalibration
1811 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1812 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1813 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1814 }
1815 }
1816
1817 mLocked.orientedRanges.orientation.min = - M_PI_2;
1818 mLocked.orientedRanges.orientation.max = M_PI_2;
1819 mLocked.orientedRanges.orientation.flat = 0;
1820 mLocked.orientedRanges.orientation.fuzz = 0;
1821 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001822 }
1823
1824 if (orientationChanged || sizeChanged) {
1825 // Compute oriented surface dimensions, precision, and scales.
1826 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001827 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001828 case DISPLAY_ORIENTATION_90:
1829 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001830 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1831 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1832 mLocked.orientedXPrecision = mLocked.yPrecision;
1833 mLocked.orientedYPrecision = mLocked.xPrecision;
1834 orientedXScale = mLocked.yScale;
1835 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001836 break;
1837 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001838 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1839 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1840 mLocked.orientedXPrecision = mLocked.xPrecision;
1841 mLocked.orientedYPrecision = mLocked.yPrecision;
1842 orientedXScale = mLocked.xScale;
1843 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001844 break;
1845 }
1846
1847 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001848 mLocked.orientedRanges.x.min = 0;
1849 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1850 mLocked.orientedRanges.x.flat = 0;
1851 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001852
Jeff Brown6328cdc2010-07-29 18:18:33 -07001853 mLocked.orientedRanges.y.min = 0;
1854 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1855 mLocked.orientedRanges.y.flat = 0;
1856 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001857 }
1858
1859 return true;
1860}
1861
Jeff Brownef3d7e82010-09-30 14:33:04 -07001862void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1863 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1864 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1865 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001866}
1867
Jeff Brown6328cdc2010-07-29 18:18:33 -07001868void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001869 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001870
Jeff Brown8d608662010-08-30 03:02:23 -07001871 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001872 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001873
Jeff Brown6328cdc2010-07-29 18:18:33 -07001874 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001875
Jeff Brown6328cdc2010-07-29 18:18:33 -07001876 if (virtualKeyDefinitions.size() == 0) {
1877 return;
1878 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001879
Jeff Brown6328cdc2010-07-29 18:18:33 -07001880 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1881
Jeff Brown8d608662010-08-30 03:02:23 -07001882 int32_t touchScreenLeft = mRawAxes.x.minValue;
1883 int32_t touchScreenTop = mRawAxes.y.minValue;
1884 int32_t touchScreenWidth = mRawAxes.x.getRange();
1885 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001886
1887 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001888 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001889 virtualKeyDefinitions[i];
1890
1891 mLocked.virtualKeys.add();
1892 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1893
1894 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1895 int32_t keyCode;
1896 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001897 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001898 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001899 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1900 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001901 mLocked.virtualKeys.pop(); // drop the key
1902 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001903 }
1904
Jeff Brown6328cdc2010-07-29 18:18:33 -07001905 virtualKey.keyCode = keyCode;
1906 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001907
Jeff Brown6328cdc2010-07-29 18:18:33 -07001908 // convert the key definition's display coordinates into touch coordinates for a hit box
1909 int32_t halfWidth = virtualKeyDefinition.width / 2;
1910 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001911
Jeff Brown6328cdc2010-07-29 18:18:33 -07001912 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1913 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1914 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1915 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1916 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1917 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1918 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1919 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001920
Jeff Brownef3d7e82010-09-30 14:33:04 -07001921 }
1922}
1923
1924void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1925 if (!mLocked.virtualKeys.isEmpty()) {
1926 dump.append(INDENT3 "Virtual Keys:\n");
1927
1928 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1929 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1930 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1931 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1932 i, virtualKey.scanCode, virtualKey.keyCode,
1933 virtualKey.hitLeft, virtualKey.hitRight,
1934 virtualKey.hitTop, virtualKey.hitBottom);
1935 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001936 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001937}
1938
Jeff Brown8d608662010-08-30 03:02:23 -07001939void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001940 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001941 Calibration& out = mCalibration;
1942
Jeff Brown511ee5f2010-10-18 13:32:20 -07001943 // Position
1944 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1945 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1946 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1947 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1948
Jeff Brownc6d282b2010-10-14 21:42:15 -07001949 // Touch Size
1950 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1951 String8 touchSizeCalibrationString;
1952 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1953 if (touchSizeCalibrationString == "none") {
1954 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1955 } else if (touchSizeCalibrationString == "geometric") {
1956 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1957 } else if (touchSizeCalibrationString == "pressure") {
1958 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1959 } else if (touchSizeCalibrationString != "default") {
1960 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1961 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001962 }
1963 }
1964
Jeff Brownc6d282b2010-10-14 21:42:15 -07001965 // Tool Size
1966 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1967 String8 toolSizeCalibrationString;
1968 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1969 if (toolSizeCalibrationString == "none") {
1970 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1971 } else if (toolSizeCalibrationString == "geometric") {
1972 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1973 } else if (toolSizeCalibrationString == "linear") {
1974 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1975 } else if (toolSizeCalibrationString == "area") {
1976 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1977 } else if (toolSizeCalibrationString != "default") {
1978 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1979 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001980 }
1981 }
1982
Jeff Brownc6d282b2010-10-14 21:42:15 -07001983 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1984 out.toolSizeLinearScale);
1985 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1986 out.toolSizeLinearBias);
1987 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1988 out.toolSizeAreaScale);
1989 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1990 out.toolSizeAreaBias);
1991 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1992 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07001993
1994 // Pressure
1995 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1996 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001997 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001998 if (pressureCalibrationString == "none") {
1999 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2000 } else if (pressureCalibrationString == "physical") {
2001 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2002 } else if (pressureCalibrationString == "amplitude") {
2003 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2004 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002005 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002006 pressureCalibrationString.string());
2007 }
2008 }
2009
2010 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2011 String8 pressureSourceString;
2012 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2013 if (pressureSourceString == "pressure") {
2014 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2015 } else if (pressureSourceString == "touch") {
2016 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2017 } else if (pressureSourceString != "default") {
2018 LOGW("Invalid value for touch.pressure.source: '%s'",
2019 pressureSourceString.string());
2020 }
2021 }
2022
2023 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2024 out.pressureScale);
2025
2026 // Size
2027 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2028 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002029 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002030 if (sizeCalibrationString == "none") {
2031 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2032 } else if (sizeCalibrationString == "normalized") {
2033 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2034 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002035 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002036 sizeCalibrationString.string());
2037 }
2038 }
2039
2040 // Orientation
2041 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2042 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002043 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002044 if (orientationCalibrationString == "none") {
2045 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2046 } else if (orientationCalibrationString == "interpolated") {
2047 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002048 } else if (orientationCalibrationString == "vector") {
2049 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002050 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002051 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002052 orientationCalibrationString.string());
2053 }
2054 }
2055}
2056
2057void TouchInputMapper::resolveCalibration() {
2058 // Pressure
2059 switch (mCalibration.pressureSource) {
2060 case Calibration::PRESSURE_SOURCE_DEFAULT:
2061 if (mRawAxes.pressure.valid) {
2062 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2063 } else if (mRawAxes.touchMajor.valid) {
2064 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2065 }
2066 break;
2067
2068 case Calibration::PRESSURE_SOURCE_PRESSURE:
2069 if (! mRawAxes.pressure.valid) {
2070 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2071 "the pressure axis is not available.");
2072 }
2073 break;
2074
2075 case Calibration::PRESSURE_SOURCE_TOUCH:
2076 if (! mRawAxes.touchMajor.valid) {
2077 LOGW("Calibration property touch.pressure.source is 'touch' but "
2078 "the touchMajor axis is not available.");
2079 }
2080 break;
2081
2082 default:
2083 break;
2084 }
2085
2086 switch (mCalibration.pressureCalibration) {
2087 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2088 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2089 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2090 } else {
2091 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2092 }
2093 break;
2094
2095 default:
2096 break;
2097 }
2098
Jeff Brownc6d282b2010-10-14 21:42:15 -07002099 // Tool Size
2100 switch (mCalibration.toolSizeCalibration) {
2101 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002102 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002103 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002104 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002105 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002106 }
2107 break;
2108
2109 default:
2110 break;
2111 }
2112
Jeff Brownc6d282b2010-10-14 21:42:15 -07002113 // Touch Size
2114 switch (mCalibration.touchSizeCalibration) {
2115 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002116 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002117 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2118 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002119 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002120 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002121 }
2122 break;
2123
2124 default:
2125 break;
2126 }
2127
2128 // Size
2129 switch (mCalibration.sizeCalibration) {
2130 case Calibration::SIZE_CALIBRATION_DEFAULT:
2131 if (mRawAxes.toolMajor.valid) {
2132 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2133 } else {
2134 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2135 }
2136 break;
2137
2138 default:
2139 break;
2140 }
2141
2142 // Orientation
2143 switch (mCalibration.orientationCalibration) {
2144 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2145 if (mRawAxes.orientation.valid) {
2146 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2147 } else {
2148 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2149 }
2150 break;
2151
2152 default:
2153 break;
2154 }
2155}
2156
Jeff Brownef3d7e82010-09-30 14:33:04 -07002157void TouchInputMapper::dumpCalibration(String8& dump) {
2158 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002159
Jeff Brown511ee5f2010-10-18 13:32:20 -07002160 // Position
2161 if (mCalibration.haveXOrigin) {
2162 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2163 }
2164 if (mCalibration.haveYOrigin) {
2165 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2166 }
2167 if (mCalibration.haveXScale) {
2168 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2169 }
2170 if (mCalibration.haveYScale) {
2171 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2172 }
2173
Jeff Brownc6d282b2010-10-14 21:42:15 -07002174 // Touch Size
2175 switch (mCalibration.touchSizeCalibration) {
2176 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2177 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002178 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002179 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2180 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002181 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002182 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2183 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002184 break;
2185 default:
2186 assert(false);
2187 }
2188
Jeff Brownc6d282b2010-10-14 21:42:15 -07002189 // Tool Size
2190 switch (mCalibration.toolSizeCalibration) {
2191 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2192 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002193 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002194 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2195 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002196 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002197 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2198 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2199 break;
2200 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2201 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002202 break;
2203 default:
2204 assert(false);
2205 }
2206
Jeff Brownc6d282b2010-10-14 21:42:15 -07002207 if (mCalibration.haveToolSizeLinearScale) {
2208 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2209 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002210 }
2211
Jeff Brownc6d282b2010-10-14 21:42:15 -07002212 if (mCalibration.haveToolSizeLinearBias) {
2213 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2214 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002215 }
2216
Jeff Brownc6d282b2010-10-14 21:42:15 -07002217 if (mCalibration.haveToolSizeAreaScale) {
2218 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2219 mCalibration.toolSizeAreaScale);
2220 }
2221
2222 if (mCalibration.haveToolSizeAreaBias) {
2223 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2224 mCalibration.toolSizeAreaBias);
2225 }
2226
2227 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002228 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002229 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002230 }
2231
2232 // Pressure
2233 switch (mCalibration.pressureCalibration) {
2234 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002235 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002236 break;
2237 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002238 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002239 break;
2240 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002241 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002242 break;
2243 default:
2244 assert(false);
2245 }
2246
2247 switch (mCalibration.pressureSource) {
2248 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002249 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002250 break;
2251 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002252 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002253 break;
2254 case Calibration::PRESSURE_SOURCE_DEFAULT:
2255 break;
2256 default:
2257 assert(false);
2258 }
2259
2260 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002261 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2262 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002263 }
2264
2265 // Size
2266 switch (mCalibration.sizeCalibration) {
2267 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002268 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002269 break;
2270 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002271 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002272 break;
2273 default:
2274 assert(false);
2275 }
2276
2277 // Orientation
2278 switch (mCalibration.orientationCalibration) {
2279 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002280 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002281 break;
2282 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002283 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002284 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002285 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2286 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2287 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002288 default:
2289 assert(false);
2290 }
2291}
2292
Jeff Brown6d0fec22010-07-23 21:28:06 -07002293void TouchInputMapper::reset() {
2294 // Synthesize touch up event if touch is currently down.
2295 // This will also take care of finishing virtual key processing if needed.
2296 if (mLastTouch.pointerCount != 0) {
2297 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2298 mCurrentTouch.clear();
2299 syncTouch(when, true);
2300 }
2301
Jeff Brown6328cdc2010-07-29 18:18:33 -07002302 { // acquire lock
2303 AutoMutex _l(mLock);
2304 initializeLocked();
2305 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002306
Jeff Brown6328cdc2010-07-29 18:18:33 -07002307 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002308}
2309
2310void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002311 uint32_t policyFlags = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002312
Jeff Brown6328cdc2010-07-29 18:18:33 -07002313 // Preprocess pointer data.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002314 if (mParameters.useBadTouchFilter) {
2315 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002316 havePointerIds = false;
2317 }
2318 }
2319
Jeff Brown6d0fec22010-07-23 21:28:06 -07002320 if (mParameters.useJumpyTouchFilter) {
2321 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002322 havePointerIds = false;
2323 }
2324 }
2325
2326 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002327 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002328 }
2329
Jeff Brown6d0fec22010-07-23 21:28:06 -07002330 TouchData temp;
2331 TouchData* savedTouch;
2332 if (mParameters.useAveragingTouchFilter) {
2333 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002334 savedTouch = & temp;
2335
Jeff Brown6d0fec22010-07-23 21:28:06 -07002336 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002337 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002338 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002339 }
2340
Jeff Brown05dc66a2011-03-02 14:41:58 -08002341 // Hide the pointer on an initial down.
2342 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
2343 getContext()->fadePointer();
2344 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002345
Jeff Brown05dc66a2011-03-02 14:41:58 -08002346 // Process touches and virtual keys.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002347 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2348 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002349 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002350 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002351 }
2352
Jeff Brown6328cdc2010-07-29 18:18:33 -07002353 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002354 if (touchResult == DROP_STROKE) {
2355 mLastTouch.clear();
2356 } else {
2357 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002358 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002359}
2360
Jeff Brown6d0fec22010-07-23 21:28:06 -07002361TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2362 nsecs_t when, uint32_t policyFlags) {
2363 int32_t keyEventAction, keyEventFlags;
2364 int32_t keyCode, scanCode, downTime;
2365 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002366
Jeff Brown6328cdc2010-07-29 18:18:33 -07002367 { // acquire lock
2368 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002369
Jeff Brown6328cdc2010-07-29 18:18:33 -07002370 // Update surface size and orientation, including virtual key positions.
2371 if (! configureSurfaceLocked()) {
2372 return DROP_STROKE;
2373 }
2374
2375 // Check for virtual key press.
2376 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002377 if (mCurrentTouch.pointerCount == 0) {
2378 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002379 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002380#if DEBUG_VIRTUAL_KEYS
2381 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002382 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002383#endif
2384 keyEventAction = AKEY_EVENT_ACTION_UP;
2385 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2386 touchResult = SKIP_TOUCH;
2387 goto DispatchVirtualKey;
2388 }
2389
2390 if (mCurrentTouch.pointerCount == 1) {
2391 int32_t x = mCurrentTouch.pointers[0].x;
2392 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002393 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2394 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002395 // Pointer is still within the space of the virtual key.
2396 return SKIP_TOUCH;
2397 }
2398 }
2399
2400 // Pointer left virtual key area or another pointer also went down.
2401 // Send key cancellation and drop the stroke so subsequent motions will be
2402 // considered fresh downs. This is useful when the user swipes away from the
2403 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002404 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002405#if DEBUG_VIRTUAL_KEYS
2406 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002407 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002408#endif
2409 keyEventAction = AKEY_EVENT_ACTION_UP;
2410 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2411 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002412
2413 // Check whether the pointer moved inside the display area where we should
2414 // start a new stroke.
2415 int32_t x = mCurrentTouch.pointers[0].x;
2416 int32_t y = mCurrentTouch.pointers[0].y;
2417 if (isPointInsideSurfaceLocked(x, y)) {
2418 mLastTouch.clear();
2419 touchResult = DISPATCH_TOUCH;
2420 } else {
2421 touchResult = DROP_STROKE;
2422 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002423 } else {
2424 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2425 // Pointer just went down. Handle off-screen touches, if needed.
2426 int32_t x = mCurrentTouch.pointers[0].x;
2427 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002428 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002429 // If exactly one pointer went down, check for virtual key hit.
2430 // Otherwise we will drop the entire stroke.
2431 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002432 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002433 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002434 if (mContext->shouldDropVirtualKey(when, getDevice(),
2435 virtualKey->keyCode, virtualKey->scanCode)) {
2436 return DROP_STROKE;
2437 }
2438
Jeff Brown6328cdc2010-07-29 18:18:33 -07002439 mLocked.currentVirtualKey.down = true;
2440 mLocked.currentVirtualKey.downTime = when;
2441 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2442 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002443#if DEBUG_VIRTUAL_KEYS
2444 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002445 mLocked.currentVirtualKey.keyCode,
2446 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002447#endif
2448 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2449 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2450 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2451 touchResult = SKIP_TOUCH;
2452 goto DispatchVirtualKey;
2453 }
2454 }
2455 return DROP_STROKE;
2456 }
2457 }
2458 return DISPATCH_TOUCH;
2459 }
2460
2461 DispatchVirtualKey:
2462 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002463 keyCode = mLocked.currentVirtualKey.keyCode;
2464 scanCode = mLocked.currentVirtualKey.scanCode;
2465 downTime = mLocked.currentVirtualKey.downTime;
2466 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002467
2468 // Dispatch virtual key.
2469 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002470 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002471 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2472 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2473 return touchResult;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002474}
2475
Jeff Brownfe508922011-01-18 15:10:10 -08002476void TouchInputMapper::detectGestures(nsecs_t when) {
2477 // Disable all virtual key touches that happen within a short time interval of the
2478 // most recent touch. The idea is to filter out stray virtual key presses when
2479 // interacting with the touch screen.
2480 //
2481 // Problems we're trying to solve:
2482 //
2483 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2484 // virtual key area that is implemented by a separate touch panel and accidentally
2485 // triggers a virtual key.
2486 //
2487 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2488 // area and accidentally triggers a virtual key. This often happens when virtual keys
2489 // are layed out below the screen near to where the on screen keyboard's space bar
2490 // is displayed.
2491 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2492 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2493 }
2494}
2495
Jeff Brown6d0fec22010-07-23 21:28:06 -07002496void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2497 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2498 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002499 if (currentPointerCount == 0 && lastPointerCount == 0) {
2500 return; // nothing to do!
2501 }
2502
Jeff Brown6d0fec22010-07-23 21:28:06 -07002503 BitSet32 currentIdBits = mCurrentTouch.idBits;
2504 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002505
2506 if (currentIdBits == lastIdBits) {
2507 // No pointer id changes so this is a move event.
2508 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002509 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002510 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002511 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002512 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002513 // There may be pointers going up and pointers going down and pointers moving
2514 // all at the same time.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002515 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2516 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2517 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002518 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002519
Jeff Brownc3db8582010-10-20 15:33:38 -07002520 // Produce an intermediate representation of the touch data that consists of the
2521 // old location of pointers that have just gone up and the new location of pointers that
2522 // have just moved but omits the location of pointers that have just gone down.
2523 TouchData interimTouch;
2524 interimTouch.copyFrom(mLastTouch);
2525
2526 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2527 bool moveNeeded = false;
2528 while (!moveIdBits.isEmpty()) {
2529 uint32_t moveId = moveIdBits.firstMarkedBit();
2530 moveIdBits.clearBit(moveId);
2531
2532 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2533 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2534 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2535 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2536 moveNeeded = true;
2537 }
2538 }
2539
2540 // Dispatch pointer up events using the interim pointer locations.
2541 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002542 uint32_t upId = upIdBits.firstMarkedBit();
2543 upIdBits.clearBit(upId);
2544 BitSet32 oldActiveIdBits = activeIdBits;
2545 activeIdBits.clearBit(upId);
2546
2547 int32_t motionEventAction;
2548 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002549 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002550 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002551 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002552 }
2553
Jeff Brownc3db8582010-10-20 15:33:38 -07002554 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002555 oldActiveIdBits, upId, pointerCount, motionEventAction);
2556 pointerCount -= 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002557 }
2558
Jeff Brownc3db8582010-10-20 15:33:38 -07002559 // Dispatch move events if any of the remaining pointers moved from their old locations.
2560 // Although applications receive new locations as part of individual pointer up
2561 // events, they do not generally handle them except when presented in a move event.
2562 if (moveNeeded) {
2563 dispatchTouch(when, policyFlags, &mCurrentTouch,
2564 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2565 }
2566
2567 // Dispatch pointer down events using the new pointer locations.
2568 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002569 uint32_t downId = downIdBits.firstMarkedBit();
2570 downIdBits.clearBit(downId);
2571 BitSet32 oldActiveIdBits = activeIdBits;
2572 activeIdBits.markBit(downId);
2573
2574 int32_t motionEventAction;
2575 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002576 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002577 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002578 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002579 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002580 }
2581
Jeff Brown8d608662010-08-30 03:02:23 -07002582 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002583 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002584 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002585 }
2586 }
2587}
2588
Jeff Brown6d0fec22010-07-23 21:28:06 -07002589void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002590 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002591 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002592 int32_t pointerIds[MAX_POINTERS];
2593 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac02010-04-22 18:58:52 -07002594 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002595 float xPrecision, yPrecision;
2596
2597 { // acquire lock
2598 AutoMutex _l(mLock);
2599
2600 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2601 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002602 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002603 uint32_t id = idBits.firstMarkedBit();
2604 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002605 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002606
Jeff Brown8d608662010-08-30 03:02:23 -07002607 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002608
Jeff Brown8d608662010-08-30 03:02:23 -07002609 // X and Y
2610 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2611 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002612
Jeff Brown8d608662010-08-30 03:02:23 -07002613 // ToolMajor and ToolMinor
2614 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002615 switch (mCalibration.toolSizeCalibration) {
2616 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002617 toolMajor = in.toolMajor * mLocked.geometricScale;
2618 if (mRawAxes.toolMinor.valid) {
2619 toolMinor = in.toolMinor * mLocked.geometricScale;
2620 } else {
2621 toolMinor = toolMajor;
2622 }
2623 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002624 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002625 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002626 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002627 : 0;
2628 if (mRawAxes.toolMinor.valid) {
2629 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002630 ? in.toolMinor * mLocked.toolSizeLinearScale
2631 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002632 : 0;
2633 } else {
2634 toolMinor = toolMajor;
2635 }
2636 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002637 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2638 if (in.toolMajor != 0) {
2639 float diameter = sqrtf(in.toolMajor
2640 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2641 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2642 } else {
2643 toolMajor = 0;
2644 }
2645 toolMinor = toolMajor;
2646 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002647 default:
2648 toolMajor = 0;
2649 toolMinor = 0;
2650 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002651 }
2652
Jeff Brownc6d282b2010-10-14 21:42:15 -07002653 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002654 toolMajor /= pointerCount;
2655 toolMinor /= pointerCount;
2656 }
2657
2658 // Pressure
2659 float rawPressure;
2660 switch (mCalibration.pressureSource) {
2661 case Calibration::PRESSURE_SOURCE_PRESSURE:
2662 rawPressure = in.pressure;
2663 break;
2664 case Calibration::PRESSURE_SOURCE_TOUCH:
2665 rawPressure = in.touchMajor;
2666 break;
2667 default:
2668 rawPressure = 0;
2669 }
2670
2671 float pressure;
2672 switch (mCalibration.pressureCalibration) {
2673 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2674 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2675 pressure = rawPressure * mLocked.pressureScale;
2676 break;
2677 default:
2678 pressure = 1;
2679 break;
2680 }
2681
2682 // TouchMajor and TouchMinor
2683 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002684 switch (mCalibration.touchSizeCalibration) {
2685 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002686 touchMajor = in.touchMajor * mLocked.geometricScale;
2687 if (mRawAxes.touchMinor.valid) {
2688 touchMinor = in.touchMinor * mLocked.geometricScale;
2689 } else {
2690 touchMinor = touchMajor;
2691 }
2692 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002693 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002694 touchMajor = toolMajor * pressure;
2695 touchMinor = toolMinor * pressure;
2696 break;
2697 default:
2698 touchMajor = 0;
2699 touchMinor = 0;
2700 break;
2701 }
2702
2703 if (touchMajor > toolMajor) {
2704 touchMajor = toolMajor;
2705 }
2706 if (touchMinor > toolMinor) {
2707 touchMinor = toolMinor;
2708 }
2709
2710 // Size
2711 float size;
2712 switch (mCalibration.sizeCalibration) {
2713 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2714 float rawSize = mRawAxes.toolMinor.valid
2715 ? avg(in.toolMajor, in.toolMinor)
2716 : in.toolMajor;
2717 size = rawSize * mLocked.sizeScale;
2718 break;
2719 }
2720 default:
2721 size = 0;
2722 break;
2723 }
2724
2725 // Orientation
2726 float orientation;
2727 switch (mCalibration.orientationCalibration) {
2728 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2729 orientation = in.orientation * mLocked.orientationScale;
2730 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002731 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2732 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2733 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2734 if (c1 != 0 || c2 != 0) {
2735 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002736 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2737 touchMajor *= scale;
2738 touchMinor /= scale;
2739 toolMajor *= scale;
2740 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002741 } else {
2742 orientation = 0;
2743 }
2744 break;
2745 }
Jeff Brown8d608662010-08-30 03:02:23 -07002746 default:
2747 orientation = 0;
2748 }
2749
2750 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002751 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002752 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002753 float xTemp = x;
2754 x = y;
2755 y = mLocked.surfaceWidth - xTemp;
2756 orientation -= M_PI_2;
2757 if (orientation < - M_PI_2) {
2758 orientation += M_PI;
2759 }
2760 break;
2761 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002762 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002763 x = mLocked.surfaceWidth - x;
2764 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002765 break;
2766 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002767 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002768 float xTemp = x;
2769 x = mLocked.surfaceHeight - y;
2770 y = xTemp;
2771 orientation += M_PI_2;
2772 if (orientation > M_PI_2) {
2773 orientation -= M_PI;
2774 }
2775 break;
2776 }
2777 }
2778
Jeff Brown8d608662010-08-30 03:02:23 -07002779 // Write output coords.
2780 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002781 out.clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -08002782 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2783 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2784 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2785 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2786 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2787 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2788 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2789 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2790 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002791
Jeff Brown8d608662010-08-30 03:02:23 -07002792 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002793
2794 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002795 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002796 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002797 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002798
2799 // Check edge flags by looking only at the first pointer since the flags are
2800 // global to the event.
2801 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownebbd5d12011-02-17 13:01:34 -08002802 float x = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
2803 float y = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08002804
2805 if (x <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002806 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002807 } else if (x >= mLocked.orientedSurfaceWidth) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002808 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2809 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08002810 if (y <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002811 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002812 } else if (y >= mLocked.orientedSurfaceHeight) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002813 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2814 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002815 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002816
2817 xPrecision = mLocked.orientedXPrecision;
2818 yPrecision = mLocked.orientedYPrecision;
2819 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07002820
Jeff Brown83c09682010-12-23 17:50:18 -08002821 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002822 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002823 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002824 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002825}
2826
Jeff Brown6328cdc2010-07-29 18:18:33 -07002827bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002828 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2829 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2830 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002831 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002832 return true;
2833}
2834
Jeff Brown6328cdc2010-07-29 18:18:33 -07002835const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2836 int32_t x, int32_t y) {
2837 size_t numVirtualKeys = mLocked.virtualKeys.size();
2838 for (size_t i = 0; i < numVirtualKeys; i++) {
2839 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002840
2841#if DEBUG_VIRTUAL_KEYS
2842 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2843 "left=%d, top=%d, right=%d, bottom=%d",
2844 x, y,
2845 virtualKey.keyCode, virtualKey.scanCode,
2846 virtualKey.hitLeft, virtualKey.hitTop,
2847 virtualKey.hitRight, virtualKey.hitBottom);
2848#endif
2849
2850 if (virtualKey.isHit(x, y)) {
2851 return & virtualKey;
2852 }
2853 }
2854
2855 return NULL;
2856}
2857
2858void TouchInputMapper::calculatePointerIds() {
2859 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2860 uint32_t lastPointerCount = mLastTouch.pointerCount;
2861
2862 if (currentPointerCount == 0) {
2863 // No pointers to assign.
2864 mCurrentTouch.idBits.clear();
2865 } else if (lastPointerCount == 0) {
2866 // All pointers are new.
2867 mCurrentTouch.idBits.clear();
2868 for (uint32_t i = 0; i < currentPointerCount; i++) {
2869 mCurrentTouch.pointers[i].id = i;
2870 mCurrentTouch.idToIndex[i] = i;
2871 mCurrentTouch.idBits.markBit(i);
2872 }
2873 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2874 // Only one pointer and no change in count so it must have the same id as before.
2875 uint32_t id = mLastTouch.pointers[0].id;
2876 mCurrentTouch.pointers[0].id = id;
2877 mCurrentTouch.idToIndex[id] = 0;
2878 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2879 } else {
2880 // General case.
2881 // We build a heap of squared euclidean distances between current and last pointers
2882 // associated with the current and last pointer indices. Then, we find the best
2883 // match (by distance) for each current pointer.
2884 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2885
2886 uint32_t heapSize = 0;
2887 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2888 currentPointerIndex++) {
2889 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2890 lastPointerIndex++) {
2891 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2892 - mLastTouch.pointers[lastPointerIndex].x;
2893 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2894 - mLastTouch.pointers[lastPointerIndex].y;
2895
2896 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2897
2898 // Insert new element into the heap (sift up).
2899 heap[heapSize].currentPointerIndex = currentPointerIndex;
2900 heap[heapSize].lastPointerIndex = lastPointerIndex;
2901 heap[heapSize].distance = distance;
2902 heapSize += 1;
2903 }
2904 }
2905
2906 // Heapify
2907 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2908 startIndex -= 1;
2909 for (uint32_t parentIndex = startIndex; ;) {
2910 uint32_t childIndex = parentIndex * 2 + 1;
2911 if (childIndex >= heapSize) {
2912 break;
2913 }
2914
2915 if (childIndex + 1 < heapSize
2916 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2917 childIndex += 1;
2918 }
2919
2920 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2921 break;
2922 }
2923
2924 swap(heap[parentIndex], heap[childIndex]);
2925 parentIndex = childIndex;
2926 }
2927 }
2928
2929#if DEBUG_POINTER_ASSIGNMENT
2930 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2931 for (size_t i = 0; i < heapSize; i++) {
2932 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2933 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2934 heap[i].distance);
2935 }
2936#endif
2937
2938 // Pull matches out by increasing order of distance.
2939 // To avoid reassigning pointers that have already been matched, the loop keeps track
2940 // of which last and current pointers have been matched using the matchedXXXBits variables.
2941 // It also tracks the used pointer id bits.
2942 BitSet32 matchedLastBits(0);
2943 BitSet32 matchedCurrentBits(0);
2944 BitSet32 usedIdBits(0);
2945 bool first = true;
2946 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2947 for (;;) {
2948 if (first) {
2949 // The first time through the loop, we just consume the root element of
2950 // the heap (the one with smallest distance).
2951 first = false;
2952 } else {
2953 // Previous iterations consumed the root element of the heap.
2954 // Pop root element off of the heap (sift down).
2955 heapSize -= 1;
2956 assert(heapSize > 0);
2957
2958 // Sift down.
2959 heap[0] = heap[heapSize];
2960 for (uint32_t parentIndex = 0; ;) {
2961 uint32_t childIndex = parentIndex * 2 + 1;
2962 if (childIndex >= heapSize) {
2963 break;
2964 }
2965
2966 if (childIndex + 1 < heapSize
2967 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2968 childIndex += 1;
2969 }
2970
2971 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2972 break;
2973 }
2974
2975 swap(heap[parentIndex], heap[childIndex]);
2976 parentIndex = childIndex;
2977 }
2978
2979#if DEBUG_POINTER_ASSIGNMENT
2980 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2981 for (size_t i = 0; i < heapSize; i++) {
2982 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2983 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2984 heap[i].distance);
2985 }
2986#endif
2987 }
2988
2989 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2990 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2991
2992 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2993 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2994
2995 matchedCurrentBits.markBit(currentPointerIndex);
2996 matchedLastBits.markBit(lastPointerIndex);
2997
2998 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2999 mCurrentTouch.pointers[currentPointerIndex].id = id;
3000 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3001 usedIdBits.markBit(id);
3002
3003#if DEBUG_POINTER_ASSIGNMENT
3004 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
3005 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
3006#endif
3007 break;
3008 }
3009 }
3010
3011 // Assign fresh ids to new pointers.
3012 if (currentPointerCount > lastPointerCount) {
3013 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
3014 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
3015 uint32_t id = usedIdBits.firstUnmarkedBit();
3016
3017 mCurrentTouch.pointers[currentPointerIndex].id = id;
3018 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3019 usedIdBits.markBit(id);
3020
3021#if DEBUG_POINTER_ASSIGNMENT
3022 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
3023 currentPointerIndex, id);
3024#endif
3025
3026 if (--i == 0) break; // done
3027 matchedCurrentBits.markBit(currentPointerIndex);
3028 }
3029 }
3030
3031 // Fix id bits.
3032 mCurrentTouch.idBits = usedIdBits;
3033 }
3034}
3035
3036/* Special hack for devices that have bad screen data: if one of the
3037 * points has moved more than a screen height from the last position,
3038 * then drop it. */
3039bool TouchInputMapper::applyBadTouchFilter() {
3040 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003041 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003042 return false;
3043 }
3044
3045 uint32_t pointerCount = mCurrentTouch.pointerCount;
3046
3047 // Nothing to do if there are no points.
3048 if (pointerCount == 0) {
3049 return false;
3050 }
3051
3052 // Don't do anything if a finger is going down or up. We run
3053 // here before assigning pointer IDs, so there isn't a good
3054 // way to do per-finger matching.
3055 if (pointerCount != mLastTouch.pointerCount) {
3056 return false;
3057 }
3058
3059 // We consider a single movement across more than a 7/16 of
3060 // the long size of the screen to be bad. This was a magic value
3061 // determined by looking at the maximum distance it is feasible
3062 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07003063 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003064
3065 // XXX The original code in InputDevice.java included commented out
3066 // code for testing the X axis. Note that when we drop a point
3067 // we don't actually restore the old X either. Strange.
3068 // The old code also tries to track when bad points were previously
3069 // detected but it turns out that due to the placement of a "break"
3070 // at the end of the loop, we never set mDroppedBadPoint to true
3071 // so it is effectively dead code.
3072 // Need to figure out if the old code is busted or just overcomplicated
3073 // but working as intended.
3074
3075 // Look through all new points and see if any are farther than
3076 // acceptable from all previous points.
3077 for (uint32_t i = pointerCount; i-- > 0; ) {
3078 int32_t y = mCurrentTouch.pointers[i].y;
3079 int32_t closestY = INT_MAX;
3080 int32_t closestDeltaY = 0;
3081
3082#if DEBUG_HACKS
3083 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3084#endif
3085
3086 for (uint32_t j = pointerCount; j-- > 0; ) {
3087 int32_t lastY = mLastTouch.pointers[j].y;
3088 int32_t deltaY = abs(y - lastY);
3089
3090#if DEBUG_HACKS
3091 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3092 j, lastY, deltaY);
3093#endif
3094
3095 if (deltaY < maxDeltaY) {
3096 goto SkipSufficientlyClosePoint;
3097 }
3098 if (deltaY < closestDeltaY) {
3099 closestDeltaY = deltaY;
3100 closestY = lastY;
3101 }
3102 }
3103
3104 // Must not have found a close enough match.
3105#if DEBUG_HACKS
3106 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3107 i, y, closestY, closestDeltaY, maxDeltaY);
3108#endif
3109
3110 mCurrentTouch.pointers[i].y = closestY;
3111 return true; // XXX original code only corrects one point
3112
3113 SkipSufficientlyClosePoint: ;
3114 }
3115
3116 // No change.
3117 return false;
3118}
3119
3120/* Special hack for devices that have bad screen data: drop points where
3121 * the coordinate value for one axis has jumped to the other pointer's location.
3122 */
3123bool TouchInputMapper::applyJumpyTouchFilter() {
3124 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003125 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003126 return false;
3127 }
3128
3129 uint32_t pointerCount = mCurrentTouch.pointerCount;
3130 if (mLastTouch.pointerCount != pointerCount) {
3131#if DEBUG_HACKS
3132 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3133 mLastTouch.pointerCount, pointerCount);
3134 for (uint32_t i = 0; i < pointerCount; i++) {
3135 LOGD(" Pointer %d (%d, %d)", i,
3136 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3137 }
3138#endif
3139
3140 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3141 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3142 // Just drop the first few events going from 1 to 2 pointers.
3143 // They're bad often enough that they're not worth considering.
3144 mCurrentTouch.pointerCount = 1;
3145 mJumpyTouchFilter.jumpyPointsDropped += 1;
3146
3147#if DEBUG_HACKS
3148 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3149#endif
3150 return true;
3151 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3152 // The event when we go from 2 -> 1 tends to be messed up too
3153 mCurrentTouch.pointerCount = 2;
3154 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3155 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3156 mJumpyTouchFilter.jumpyPointsDropped += 1;
3157
3158#if DEBUG_HACKS
3159 for (int32_t i = 0; i < 2; i++) {
3160 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3161 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3162 }
3163#endif
3164 return true;
3165 }
3166 }
3167 // Reset jumpy points dropped on other transitions or if limit exceeded.
3168 mJumpyTouchFilter.jumpyPointsDropped = 0;
3169
3170#if DEBUG_HACKS
3171 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3172#endif
3173 return false;
3174 }
3175
3176 // We have the same number of pointers as last time.
3177 // A 'jumpy' point is one where the coordinate value for one axis
3178 // has jumped to the other pointer's location. No need to do anything
3179 // else if we only have one pointer.
3180 if (pointerCount < 2) {
3181 return false;
3182 }
3183
3184 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003185 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003186
3187 // We only replace the single worst jumpy point as characterized by pointer distance
3188 // in a single axis.
3189 int32_t badPointerIndex = -1;
3190 int32_t badPointerReplacementIndex = -1;
3191 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3192
3193 for (uint32_t i = pointerCount; i-- > 0; ) {
3194 int32_t x = mCurrentTouch.pointers[i].x;
3195 int32_t y = mCurrentTouch.pointers[i].y;
3196
3197#if DEBUG_HACKS
3198 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3199#endif
3200
3201 // Check if a touch point is too close to another's coordinates
3202 bool dropX = false, dropY = false;
3203 for (uint32_t j = 0; j < pointerCount; j++) {
3204 if (i == j) {
3205 continue;
3206 }
3207
3208 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3209 dropX = true;
3210 break;
3211 }
3212
3213 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3214 dropY = true;
3215 break;
3216 }
3217 }
3218 if (! dropX && ! dropY) {
3219 continue; // not jumpy
3220 }
3221
3222 // Find a replacement candidate by comparing with older points on the
3223 // complementary (non-jumpy) axis.
3224 int32_t distance = INT_MIN; // distance to be corrected
3225 int32_t replacementIndex = -1;
3226
3227 if (dropX) {
3228 // X looks too close. Find an older replacement point with a close Y.
3229 int32_t smallestDeltaY = INT_MAX;
3230 for (uint32_t j = 0; j < pointerCount; j++) {
3231 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3232 if (deltaY < smallestDeltaY) {
3233 smallestDeltaY = deltaY;
3234 replacementIndex = j;
3235 }
3236 }
3237 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3238 } else {
3239 // Y looks too close. Find an older replacement point with a close X.
3240 int32_t smallestDeltaX = INT_MAX;
3241 for (uint32_t j = 0; j < pointerCount; j++) {
3242 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3243 if (deltaX < smallestDeltaX) {
3244 smallestDeltaX = deltaX;
3245 replacementIndex = j;
3246 }
3247 }
3248 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3249 }
3250
3251 // If replacing this pointer would correct a worse error than the previous ones
3252 // considered, then use this replacement instead.
3253 if (distance > badPointerDistance) {
3254 badPointerIndex = i;
3255 badPointerReplacementIndex = replacementIndex;
3256 badPointerDistance = distance;
3257 }
3258 }
3259
3260 // Correct the jumpy pointer if one was found.
3261 if (badPointerIndex >= 0) {
3262#if DEBUG_HACKS
3263 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3264 badPointerIndex,
3265 mLastTouch.pointers[badPointerReplacementIndex].x,
3266 mLastTouch.pointers[badPointerReplacementIndex].y);
3267#endif
3268
3269 mCurrentTouch.pointers[badPointerIndex].x =
3270 mLastTouch.pointers[badPointerReplacementIndex].x;
3271 mCurrentTouch.pointers[badPointerIndex].y =
3272 mLastTouch.pointers[badPointerReplacementIndex].y;
3273 mJumpyTouchFilter.jumpyPointsDropped += 1;
3274 return true;
3275 }
3276 }
3277
3278 mJumpyTouchFilter.jumpyPointsDropped = 0;
3279 return false;
3280}
3281
3282/* Special hack for devices that have bad screen data: aggregate and
3283 * compute averages of the coordinate data, to reduce the amount of
3284 * jitter seen by applications. */
3285void TouchInputMapper::applyAveragingTouchFilter() {
3286 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3287 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3288 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3289 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003290 int32_t pressure;
3291 switch (mCalibration.pressureSource) {
3292 case Calibration::PRESSURE_SOURCE_PRESSURE:
3293 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3294 break;
3295 case Calibration::PRESSURE_SOURCE_TOUCH:
3296 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3297 break;
3298 default:
3299 pressure = 1;
3300 break;
3301 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003302
3303 if (mLastTouch.idBits.hasBit(id)) {
3304 // Pointer was down before and is still down now.
3305 // Compute average over history trace.
3306 uint32_t start = mAveragingTouchFilter.historyStart[id];
3307 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3308
3309 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3310 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3311 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3312
3313#if DEBUG_HACKS
3314 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3315 id, distance);
3316#endif
3317
3318 if (distance < AVERAGING_DISTANCE_LIMIT) {
3319 // Increment end index in preparation for recording new historical data.
3320 end += 1;
3321 if (end > AVERAGING_HISTORY_SIZE) {
3322 end = 0;
3323 }
3324
3325 // If the end index has looped back to the start index then we have filled
3326 // the historical trace up to the desired size so we drop the historical
3327 // data at the start of the trace.
3328 if (end == start) {
3329 start += 1;
3330 if (start > AVERAGING_HISTORY_SIZE) {
3331 start = 0;
3332 }
3333 }
3334
3335 // Add the raw data to the historical trace.
3336 mAveragingTouchFilter.historyStart[id] = start;
3337 mAveragingTouchFilter.historyEnd[id] = end;
3338 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3339 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3340 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3341
3342 // Average over all historical positions in the trace by total pressure.
3343 int32_t averagedX = 0;
3344 int32_t averagedY = 0;
3345 int32_t totalPressure = 0;
3346 for (;;) {
3347 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3348 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3349 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3350 .pointers[id].pressure;
3351
3352 averagedX += historicalX * historicalPressure;
3353 averagedY += historicalY * historicalPressure;
3354 totalPressure += historicalPressure;
3355
3356 if (start == end) {
3357 break;
3358 }
3359
3360 start += 1;
3361 if (start > AVERAGING_HISTORY_SIZE) {
3362 start = 0;
3363 }
3364 }
3365
Jeff Brown8d608662010-08-30 03:02:23 -07003366 if (totalPressure != 0) {
3367 averagedX /= totalPressure;
3368 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003369
3370#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003371 LOGD("AveragingTouchFilter: Pointer id %d - "
3372 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3373 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003374#endif
3375
Jeff Brown8d608662010-08-30 03:02:23 -07003376 mCurrentTouch.pointers[currentIndex].x = averagedX;
3377 mCurrentTouch.pointers[currentIndex].y = averagedY;
3378 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003379 } else {
3380#if DEBUG_HACKS
3381 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3382#endif
3383 }
3384 } else {
3385#if DEBUG_HACKS
3386 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3387#endif
3388 }
3389
3390 // Reset pointer history.
3391 mAveragingTouchFilter.historyStart[id] = 0;
3392 mAveragingTouchFilter.historyEnd[id] = 0;
3393 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3394 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3395 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3396 }
3397}
3398
3399int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003400 { // acquire lock
3401 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003402
Jeff Brown6328cdc2010-07-29 18:18:33 -07003403 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003404 return AKEY_STATE_VIRTUAL;
3405 }
3406
Jeff Brown6328cdc2010-07-29 18:18:33 -07003407 size_t numVirtualKeys = mLocked.virtualKeys.size();
3408 for (size_t i = 0; i < numVirtualKeys; i++) {
3409 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003410 if (virtualKey.keyCode == keyCode) {
3411 return AKEY_STATE_UP;
3412 }
3413 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003414 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003415
3416 return AKEY_STATE_UNKNOWN;
3417}
3418
3419int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003420 { // acquire lock
3421 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003422
Jeff Brown6328cdc2010-07-29 18:18:33 -07003423 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003424 return AKEY_STATE_VIRTUAL;
3425 }
3426
Jeff Brown6328cdc2010-07-29 18:18:33 -07003427 size_t numVirtualKeys = mLocked.virtualKeys.size();
3428 for (size_t i = 0; i < numVirtualKeys; i++) {
3429 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003430 if (virtualKey.scanCode == scanCode) {
3431 return AKEY_STATE_UP;
3432 }
3433 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003434 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003435
3436 return AKEY_STATE_UNKNOWN;
3437}
3438
3439bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3440 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003441 { // acquire lock
3442 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003443
Jeff Brown6328cdc2010-07-29 18:18:33 -07003444 size_t numVirtualKeys = mLocked.virtualKeys.size();
3445 for (size_t i = 0; i < numVirtualKeys; i++) {
3446 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003447
3448 for (size_t i = 0; i < numCodes; i++) {
3449 if (virtualKey.keyCode == keyCodes[i]) {
3450 outFlags[i] = 1;
3451 }
3452 }
3453 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003454 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003455
3456 return true;
3457}
3458
3459
3460// --- SingleTouchInputMapper ---
3461
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003462SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3463 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003464 initialize();
3465}
3466
3467SingleTouchInputMapper::~SingleTouchInputMapper() {
3468}
3469
3470void SingleTouchInputMapper::initialize() {
3471 mAccumulator.clear();
3472
3473 mDown = false;
3474 mX = 0;
3475 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003476 mPressure = 0; // default to 0 for devices that don't report pressure
3477 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003478}
3479
3480void SingleTouchInputMapper::reset() {
3481 TouchInputMapper::reset();
3482
Jeff Brown6d0fec22010-07-23 21:28:06 -07003483 initialize();
3484 }
3485
3486void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3487 switch (rawEvent->type) {
3488 case EV_KEY:
3489 switch (rawEvent->scanCode) {
3490 case BTN_TOUCH:
3491 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3492 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003493 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3494 // not have received valid position information yet. This logic assumes that
3495 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003496 break;
3497 }
3498 break;
3499
3500 case EV_ABS:
3501 switch (rawEvent->scanCode) {
3502 case ABS_X:
3503 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3504 mAccumulator.absX = rawEvent->value;
3505 break;
3506 case ABS_Y:
3507 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3508 mAccumulator.absY = rawEvent->value;
3509 break;
3510 case ABS_PRESSURE:
3511 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3512 mAccumulator.absPressure = rawEvent->value;
3513 break;
3514 case ABS_TOOL_WIDTH:
3515 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3516 mAccumulator.absToolWidth = rawEvent->value;
3517 break;
3518 }
3519 break;
3520
3521 case EV_SYN:
3522 switch (rawEvent->scanCode) {
3523 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003524 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003525 break;
3526 }
3527 break;
3528 }
3529}
3530
3531void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003532 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003533 if (fields == 0) {
3534 return; // no new state changes, so nothing to do
3535 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003536
3537 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3538 mDown = mAccumulator.btnTouch;
3539 }
3540
3541 if (fields & Accumulator::FIELD_ABS_X) {
3542 mX = mAccumulator.absX;
3543 }
3544
3545 if (fields & Accumulator::FIELD_ABS_Y) {
3546 mY = mAccumulator.absY;
3547 }
3548
3549 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3550 mPressure = mAccumulator.absPressure;
3551 }
3552
3553 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003554 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003555 }
3556
3557 mCurrentTouch.clear();
3558
3559 if (mDown) {
3560 mCurrentTouch.pointerCount = 1;
3561 mCurrentTouch.pointers[0].id = 0;
3562 mCurrentTouch.pointers[0].x = mX;
3563 mCurrentTouch.pointers[0].y = mY;
3564 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003565 mCurrentTouch.pointers[0].touchMajor = 0;
3566 mCurrentTouch.pointers[0].touchMinor = 0;
3567 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3568 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003569 mCurrentTouch.pointers[0].orientation = 0;
3570 mCurrentTouch.idToIndex[0] = 0;
3571 mCurrentTouch.idBits.markBit(0);
3572 }
3573
3574 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003575
3576 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003577}
3578
Jeff Brown8d608662010-08-30 03:02:23 -07003579void SingleTouchInputMapper::configureRawAxes() {
3580 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003581
Jeff Brown8d608662010-08-30 03:02:23 -07003582 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3583 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3584 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3585 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003586}
3587
3588
3589// --- MultiTouchInputMapper ---
3590
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003591MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3592 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003593 initialize();
3594}
3595
3596MultiTouchInputMapper::~MultiTouchInputMapper() {
3597}
3598
3599void MultiTouchInputMapper::initialize() {
3600 mAccumulator.clear();
3601}
3602
3603void MultiTouchInputMapper::reset() {
3604 TouchInputMapper::reset();
3605
Jeff Brown6d0fec22010-07-23 21:28:06 -07003606 initialize();
3607}
3608
3609void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3610 switch (rawEvent->type) {
3611 case EV_ABS: {
3612 uint32_t pointerIndex = mAccumulator.pointerCount;
3613 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3614
3615 switch (rawEvent->scanCode) {
3616 case ABS_MT_POSITION_X:
3617 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3618 pointer->absMTPositionX = rawEvent->value;
3619 break;
3620 case ABS_MT_POSITION_Y:
3621 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3622 pointer->absMTPositionY = rawEvent->value;
3623 break;
3624 case ABS_MT_TOUCH_MAJOR:
3625 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3626 pointer->absMTTouchMajor = rawEvent->value;
3627 break;
3628 case ABS_MT_TOUCH_MINOR:
3629 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3630 pointer->absMTTouchMinor = rawEvent->value;
3631 break;
3632 case ABS_MT_WIDTH_MAJOR:
3633 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3634 pointer->absMTWidthMajor = rawEvent->value;
3635 break;
3636 case ABS_MT_WIDTH_MINOR:
3637 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3638 pointer->absMTWidthMinor = rawEvent->value;
3639 break;
3640 case ABS_MT_ORIENTATION:
3641 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3642 pointer->absMTOrientation = rawEvent->value;
3643 break;
3644 case ABS_MT_TRACKING_ID:
3645 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3646 pointer->absMTTrackingId = rawEvent->value;
3647 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003648 case ABS_MT_PRESSURE:
3649 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3650 pointer->absMTPressure = rawEvent->value;
3651 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003652 }
3653 break;
3654 }
3655
3656 case EV_SYN:
3657 switch (rawEvent->scanCode) {
3658 case SYN_MT_REPORT: {
3659 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3660 uint32_t pointerIndex = mAccumulator.pointerCount;
3661
3662 if (mAccumulator.pointers[pointerIndex].fields) {
3663 if (pointerIndex == MAX_POINTERS) {
3664 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3665 MAX_POINTERS);
3666 } else {
3667 pointerIndex += 1;
3668 mAccumulator.pointerCount = pointerIndex;
3669 }
3670 }
3671
3672 mAccumulator.pointers[pointerIndex].clear();
3673 break;
3674 }
3675
3676 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003677 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003678 break;
3679 }
3680 break;
3681 }
3682}
3683
3684void MultiTouchInputMapper::sync(nsecs_t when) {
3685 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003686 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003687
Jeff Brown6d0fec22010-07-23 21:28:06 -07003688 uint32_t inCount = mAccumulator.pointerCount;
3689 uint32_t outCount = 0;
3690 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003691
Jeff Brown6d0fec22010-07-23 21:28:06 -07003692 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003693
Jeff Brown6d0fec22010-07-23 21:28:06 -07003694 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003695 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3696 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003697
Jeff Brown6d0fec22010-07-23 21:28:06 -07003698 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003699 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3700 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07003701 continue;
3702 }
3703
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003704 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3705 outPointer.x = inPointer.absMTPositionX;
3706 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003707
Jeff Brown8d608662010-08-30 03:02:23 -07003708 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3709 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003710 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3711 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003712 continue;
3713 }
Jeff Brown8d608662010-08-30 03:02:23 -07003714 outPointer.pressure = inPointer.absMTPressure;
3715 } else {
3716 // Default pressure to 0 if absent.
3717 outPointer.pressure = 0;
3718 }
3719
3720 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3721 if (inPointer.absMTTouchMajor <= 0) {
3722 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3723 // a pointer going up. Drop this finger.
3724 continue;
3725 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003726 outPointer.touchMajor = inPointer.absMTTouchMajor;
3727 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003728 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003729 outPointer.touchMajor = 0;
3730 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003731
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003732 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3733 outPointer.touchMinor = inPointer.absMTTouchMinor;
3734 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003735 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003736 outPointer.touchMinor = outPointer.touchMajor;
3737 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003738
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003739 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3740 outPointer.toolMajor = inPointer.absMTWidthMajor;
3741 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003742 // Default tool area to 0 if absent.
3743 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003744 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003745
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003746 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3747 outPointer.toolMinor = inPointer.absMTWidthMinor;
3748 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003749 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003750 outPointer.toolMinor = outPointer.toolMajor;
3751 }
3752
3753 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3754 outPointer.orientation = inPointer.absMTOrientation;
3755 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003756 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003757 outPointer.orientation = 0;
3758 }
3759
Jeff Brown8d608662010-08-30 03:02:23 -07003760 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003761 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003762 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3763 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003764
Jeff Brown6d0fec22010-07-23 21:28:06 -07003765 if (id > MAX_POINTER_ID) {
3766#if DEBUG_POINTERS
3767 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003768 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003769 id, MAX_POINTER_ID);
3770#endif
3771 havePointerIds = false;
3772 }
3773 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003774 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003775 mCurrentTouch.idToIndex[id] = outCount;
3776 mCurrentTouch.idBits.markBit(id);
3777 }
3778 } else {
3779 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003780 }
3781 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003782
Jeff Brown6d0fec22010-07-23 21:28:06 -07003783 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003784 }
3785
Jeff Brown6d0fec22010-07-23 21:28:06 -07003786 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003787
Jeff Brown6d0fec22010-07-23 21:28:06 -07003788 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003789
3790 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003791}
3792
Jeff Brown8d608662010-08-30 03:02:23 -07003793void MultiTouchInputMapper::configureRawAxes() {
3794 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003795
Jeff Brown8d608662010-08-30 03:02:23 -07003796 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3797 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3798 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3799 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3800 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3801 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3802 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3803 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003804}
3805
Jeff Brown46b9ac02010-04-22 18:58:52 -07003806
Jeff Browncb1404e2011-01-15 18:14:15 -08003807// --- JoystickInputMapper ---
3808
3809JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3810 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08003811}
3812
3813JoystickInputMapper::~JoystickInputMapper() {
3814}
3815
3816uint32_t JoystickInputMapper::getSources() {
3817 return AINPUT_SOURCE_JOYSTICK;
3818}
3819
3820void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3821 InputMapper::populateDeviceInfo(info);
3822
Jeff Brown6f2fba42011-02-19 01:08:02 -08003823 for (size_t i = 0; i < mAxes.size(); i++) {
3824 const Axis& axis = mAxes.valueAt(i);
3825 info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003826 }
3827}
3828
3829void JoystickInputMapper::dump(String8& dump) {
3830 dump.append(INDENT2 "Joystick Input Mapper:\n");
3831
Jeff Brown6f2fba42011-02-19 01:08:02 -08003832 dump.append(INDENT3 "Axes:\n");
3833 size_t numAxes = mAxes.size();
3834 for (size_t i = 0; i < numAxes; i++) {
3835 const Axis& axis = mAxes.valueAt(i);
3836 const char* label = getAxisLabel(axis.axis);
3837 char name[32];
3838 if (label) {
3839 strncpy(name, label, sizeof(name));
3840 name[sizeof(name) - 1] = '\0';
3841 } else {
3842 snprintf(name, sizeof(name), "%d", axis.axis);
3843 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003844 dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
Jeff Brown6f2fba42011-02-19 01:08:02 -08003845 "scale=%0.3f, offset=%0.3f\n",
Jeff Browncb1404e2011-01-15 18:14:15 -08003846 name, axis.min, axis.max, axis.flat, axis.fuzz,
Jeff Brown6f2fba42011-02-19 01:08:02 -08003847 axis.scale, axis.offset);
3848 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3849 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3850 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003851 }
3852}
3853
3854void JoystickInputMapper::configure() {
3855 InputMapper::configure();
3856
Jeff Brown6f2fba42011-02-19 01:08:02 -08003857 // Collect all axes.
3858 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3859 RawAbsoluteAxisInfo rawAxisInfo;
3860 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3861 if (rawAxisInfo.valid) {
3862 int32_t axisId;
3863 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
3864 if (!explicitlyMapped) {
3865 // Axis is not explicitly mapped, will choose a generic axis later.
3866 axisId = -1;
3867 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003868
Jeff Brown6f2fba42011-02-19 01:08:02 -08003869 Axis axis;
3870 if (isCenteredAxis(axisId)) {
3871 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3872 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
3873 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3874 scale, offset, -1.0f, 1.0f,
3875 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3876 } else {
3877 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3878 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3879 scale, 0.0f, 0.0f, 1.0f,
3880 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3881 }
3882
3883 // To eliminate noise while the joystick is at rest, filter out small variations
3884 // in axis values up front.
3885 axis.filter = axis.flat * 0.25f;
3886
3887 mAxes.add(abs, axis);
3888 }
3889 }
3890
3891 // If there are too many axes, start dropping them.
3892 // Prefer to keep explicitly mapped axes.
3893 if (mAxes.size() > PointerCoords::MAX_AXES) {
3894 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3895 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3896 pruneAxes(true);
3897 pruneAxes(false);
3898 }
3899
3900 // Assign generic axis ids to remaining axes.
3901 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3902 size_t numAxes = mAxes.size();
3903 for (size_t i = 0; i < numAxes; i++) {
3904 Axis& axis = mAxes.editValueAt(i);
3905 if (axis.axis < 0) {
3906 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3907 && haveAxis(nextGenericAxisId)) {
3908 nextGenericAxisId += 1;
3909 }
3910
3911 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
3912 axis.axis = nextGenericAxisId;
3913 nextGenericAxisId += 1;
3914 } else {
3915 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3916 "have already been assigned to other axes.",
3917 getDeviceName().string(), mAxes.keyAt(i));
3918 mAxes.removeItemsAt(i--);
3919 numAxes -= 1;
3920 }
3921 }
3922 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003923}
3924
Jeff Brown6f2fba42011-02-19 01:08:02 -08003925bool JoystickInputMapper::haveAxis(int32_t axis) {
3926 size_t numAxes = mAxes.size();
3927 for (size_t i = 0; i < numAxes; i++) {
3928 if (mAxes.valueAt(i).axis == axis) {
3929 return true;
3930 }
3931 }
3932 return false;
3933}
Jeff Browncb1404e2011-01-15 18:14:15 -08003934
Jeff Brown6f2fba42011-02-19 01:08:02 -08003935void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
3936 size_t i = mAxes.size();
3937 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
3938 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
3939 continue;
3940 }
3941 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
3942 getDeviceName().string(), mAxes.keyAt(i));
3943 mAxes.removeItemsAt(i);
3944 }
3945}
3946
3947bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
3948 switch (axis) {
3949 case AMOTION_EVENT_AXIS_X:
3950 case AMOTION_EVENT_AXIS_Y:
3951 case AMOTION_EVENT_AXIS_Z:
3952 case AMOTION_EVENT_AXIS_RX:
3953 case AMOTION_EVENT_AXIS_RY:
3954 case AMOTION_EVENT_AXIS_RZ:
3955 case AMOTION_EVENT_AXIS_HAT_X:
3956 case AMOTION_EVENT_AXIS_HAT_Y:
3957 case AMOTION_EVENT_AXIS_ORIENTATION:
3958 return true;
3959 default:
3960 return false;
3961 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003962}
3963
3964void JoystickInputMapper::reset() {
3965 // Recenter all axes.
3966 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08003967
Jeff Brown6f2fba42011-02-19 01:08:02 -08003968 size_t numAxes = mAxes.size();
3969 for (size_t i = 0; i < numAxes; i++) {
3970 Axis& axis = mAxes.editValueAt(i);
3971 axis.newValue = 0;
3972 }
3973
3974 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08003975
3976 InputMapper::reset();
3977}
3978
3979void JoystickInputMapper::process(const RawEvent* rawEvent) {
3980 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003981 case EV_ABS: {
3982 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
3983 if (index >= 0) {
3984 Axis& axis = mAxes.editValueAt(index);
3985 float newValue = rawEvent->value * axis.scale + axis.offset;
3986 if (newValue != axis.newValue) {
3987 axis.newValue = newValue;
3988 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003989 }
3990 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08003991 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003992
3993 case EV_SYN:
3994 switch (rawEvent->scanCode) {
3995 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08003996 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08003997 break;
3998 }
3999 break;
4000 }
4001}
4002
Jeff Brown6f2fba42011-02-19 01:08:02 -08004003void JoystickInputMapper::sync(nsecs_t when, bool force) {
4004 if (!force && !haveAxesChangedSignificantly()) {
4005 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08004006 }
4007
4008 int32_t metaState = mContext->getGlobalMetaState();
4009
Jeff Brown6f2fba42011-02-19 01:08:02 -08004010 PointerCoords pointerCoords;
4011 pointerCoords.clear();
4012
4013 size_t numAxes = mAxes.size();
4014 for (size_t i = 0; i < numAxes; i++) {
4015 Axis& axis = mAxes.editValueAt(i);
4016 pointerCoords.setAxisValue(axis.axis, axis.newValue);
4017 axis.oldValue = axis.newValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08004018 }
4019
Jeff Brown6f2fba42011-02-19 01:08:02 -08004020 int32_t pointerId = 0;
4021 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
4022 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
4023 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08004024}
4025
Jeff Brown6f2fba42011-02-19 01:08:02 -08004026bool JoystickInputMapper::haveAxesChangedSignificantly() {
4027 size_t numAxes = mAxes.size();
4028 for (size_t i = 0; i < numAxes; i++) {
4029 const Axis& axis = mAxes.valueAt(i);
4030 if (axis.newValue != axis.oldValue
4031 && fabs(axis.newValue - axis.oldValue) > axis.filter) {
4032 return true;
4033 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004034 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08004035 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08004036}
4037
Jeff Brown46b9ac02010-04-22 18:58:52 -07004038} // namespace android