blob: ab43a20ed9a88f30a32092f342c6f03fa56b6e7c [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036#include "InputReader.h"
37
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080039#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080040#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070045#include <errno.h>
46#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070047#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048
Jeff Brown8d608662010-08-30 03:02:23 -070049#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070050#define INDENT2 " "
51#define INDENT3 " "
52#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070053
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070054namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60 return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65 return a < b ? a : b;
66}
67
Jeff Brown5c225b12010-06-16 01:53:36 -070068template<typename T>
69inline static void swap(T& a, T& b) {
70 T temp = a;
71 a = b;
72 b = temp;
73}
74
Jeff Brown8d608662010-08-30 03:02:23 -070075inline static float avg(float x, float y) {
76 return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80 return sqrtf(x * x + y * y);
81}
82
Jeff Brown517bb4c2011-01-14 19:09:23 -080083inline static int32_t signExtendNybble(int32_t value) {
84 return value >= 8 ? value - 16 : value;
85}
86
Jeff Brownef3d7e82010-09-30 14:33:04 -070087static inline const char* toString(bool value) {
88 return value ? "true" : "false";
89}
90
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070091static const int32_t keyCodeRotationMap[][4] = {
92 // key codes enumerated counter-clockwise with the original (unrotated) key first
93 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -070094 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
95 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
96 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
97 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070098};
99static const int keyCodeRotationMapSize =
100 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
101
102int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103 if (orientation != DISPLAY_ORIENTATION_0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700104 for (int i = 0; i < keyCodeRotationMapSize; i++) {
105 if (keyCode == keyCodeRotationMap[i][0]) {
106 return keyCodeRotationMap[i][orientation];
107 }
108 }
109 }
110 return keyCode;
111}
112
Jeff Brown6d0fec22010-07-23 21:28:06 -0700113static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
114 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
115}
116
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700117
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700118// --- InputReader ---
119
120InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700121 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700122 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700123 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brownfe508922011-01-18 15:10:10 -0800124 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700125 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700126 updateGlobalMetaState();
127 updateInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700128}
129
130InputReader::~InputReader() {
131 for (size_t i = 0; i < mDevices.size(); i++) {
132 delete mDevices.valueAt(i);
133 }
134}
135
136void InputReader::loopOnce() {
137 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700138 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700139
140#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800141 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700142 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
143 rawEvent.value);
144#endif
145
146 process(& rawEvent);
147}
148
149void InputReader::process(const RawEvent* rawEvent) {
150 switch (rawEvent->type) {
151 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700152 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700153 break;
154
155 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700156 removeDevice(rawEvent->deviceId);
157 break;
158
159 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700160 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700161 break;
162
Jeff Brown6d0fec22010-07-23 21:28:06 -0700163 default:
164 consumeEvent(rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700165 break;
166 }
167}
168
Jeff Brown7342bb92010-10-01 18:55:43 -0700169void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700170 String8 name = mEventHub->getDeviceName(deviceId);
171 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
172
173 InputDevice* device = createDevice(deviceId, name, classes);
174 device->configure();
175
Jeff Brown8d608662010-08-30 03:02:23 -0700176 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800177 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700178 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800179 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700180 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700181 }
182
Jeff Brown6d0fec22010-07-23 21:28:06 -0700183 bool added = false;
184 { // acquire device registry writer lock
185 RWLock::AutoWLock _wl(mDeviceRegistryLock);
186
187 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
188 if (deviceIndex < 0) {
189 mDevices.add(deviceId, device);
190 added = true;
191 }
192 } // release device registry writer lock
193
194 if (! added) {
195 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
196 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700197 return;
198 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700199}
200
Jeff Brown7342bb92010-10-01 18:55:43 -0700201void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700202 bool removed = false;
203 InputDevice* device = NULL;
204 { // acquire device registry writer lock
205 RWLock::AutoWLock _wl(mDeviceRegistryLock);
206
207 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
208 if (deviceIndex >= 0) {
209 device = mDevices.valueAt(deviceIndex);
210 mDevices.removeItemsAt(deviceIndex, 1);
211 removed = true;
212 }
213 } // release device registry writer lock
214
215 if (! removed) {
216 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800221 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 device->getId(), device->getName().string());
223 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800224 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700225 device->getId(), device->getName().string(), device->getSources());
226 }
227
Jeff Brown8d608662010-08-30 03:02:23 -0700228 device->reset();
229
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700231}
232
Jeff Brown6d0fec22010-07-23 21:28:06 -0700233InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
234 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700235
Jeff Brown56194eb2011-03-02 19:23:13 -0800236 // External devices.
237 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
238 device->setExternal(true);
239 }
240
Jeff Brown6d0fec22010-07-23 21:28:06 -0700241 // Switch-like devices.
242 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
243 device->addMapper(new SwitchInputMapper(device));
244 }
245
246 // Keyboard-like devices.
247 uint32_t keyboardSources = 0;
248 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
249 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
250 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
251 }
252 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
253 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
254 }
255 if (classes & INPUT_DEVICE_CLASS_DPAD) {
256 keyboardSources |= AINPUT_SOURCE_DPAD;
257 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800258 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
259 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
260 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700261
262 if (keyboardSources != 0) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800263 device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700264 }
265
Jeff Brown83c09682010-12-23 17:50:18 -0800266 // Cursor-like devices.
267 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
268 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700269 }
270
Jeff Brown58a2da82011-01-25 16:02:22 -0800271 // Touchscreens and touchpad devices.
272 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800273 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800274 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800275 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700276 }
277
Jeff Browncb1404e2011-01-15 18:14:15 -0800278 // Joystick-like devices.
279 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
280 device->addMapper(new JoystickInputMapper(device));
281 }
282
Jeff Brown6d0fec22010-07-23 21:28:06 -0700283 return device;
284}
285
286void InputReader::consumeEvent(const RawEvent* rawEvent) {
287 int32_t deviceId = rawEvent->deviceId;
288
289 { // acquire device registry reader lock
290 RWLock::AutoRLock _rl(mDeviceRegistryLock);
291
292 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
293 if (deviceIndex < 0) {
294 LOGW("Discarding event for unknown deviceId %d.", deviceId);
295 return;
296 }
297
298 InputDevice* device = mDevices.valueAt(deviceIndex);
299 if (device->isIgnored()) {
300 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
301 return;
302 }
303
304 device->process(rawEvent);
305 } // release device registry reader lock
306}
307
Jeff Brownc3db8582010-10-20 15:33:38 -0700308void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700309 // Reset global meta state because it depends on the list of all configured devices.
310 updateGlobalMetaState();
311
312 // Update input configuration.
313 updateInputConfiguration();
314
315 // Enqueue configuration changed.
316 mDispatcher->notifyConfigurationChanged(when);
317}
318
319void InputReader::configureExcludedDevices() {
320 Vector<String8> excludedDeviceNames;
321 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
322
323 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
324 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
325 }
326}
327
328void InputReader::updateGlobalMetaState() {
329 { // acquire state lock
330 AutoMutex _l(mStateLock);
331
332 mGlobalMetaState = 0;
333
334 { // acquire device registry reader lock
335 RWLock::AutoRLock _rl(mDeviceRegistryLock);
336
337 for (size_t i = 0; i < mDevices.size(); i++) {
338 InputDevice* device = mDevices.valueAt(i);
339 mGlobalMetaState |= device->getMetaState();
340 }
341 } // release device registry reader lock
342 } // release state lock
343}
344
345int32_t InputReader::getGlobalMetaState() {
346 { // acquire state lock
347 AutoMutex _l(mStateLock);
348
349 return mGlobalMetaState;
350 } // release state lock
351}
352
353void InputReader::updateInputConfiguration() {
354 { // acquire state lock
355 AutoMutex _l(mStateLock);
356
357 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
358 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
359 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
360 { // acquire device registry reader lock
361 RWLock::AutoRLock _rl(mDeviceRegistryLock);
362
363 InputDeviceInfo deviceInfo;
364 for (size_t i = 0; i < mDevices.size(); i++) {
365 InputDevice* device = mDevices.valueAt(i);
366 device->getDeviceInfo(& deviceInfo);
367 uint32_t sources = deviceInfo.getSources();
368
369 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
370 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
371 }
372 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
373 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
374 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
375 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
376 }
377 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
378 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700379 }
380 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700381 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700382
Jeff Brown6d0fec22010-07-23 21:28:06 -0700383 mInputConfiguration.touchScreen = touchScreenConfig;
384 mInputConfiguration.keyboard = keyboardConfig;
385 mInputConfiguration.navigation = navigationConfig;
386 } // release state lock
387}
388
Jeff Brownfe508922011-01-18 15:10:10 -0800389void InputReader::disableVirtualKeysUntil(nsecs_t time) {
390 mDisableVirtualKeysTimeout = time;
391}
392
393bool InputReader::shouldDropVirtualKey(nsecs_t now,
394 InputDevice* device, int32_t keyCode, int32_t scanCode) {
395 if (now < mDisableVirtualKeysTimeout) {
396 LOGI("Dropping virtual key from device %s because virtual keys are "
397 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
398 device->getName().string(),
399 (mDisableVirtualKeysTimeout - now) * 0.000001,
400 keyCode, scanCode);
401 return true;
402 } else {
403 return false;
404 }
405}
406
Jeff Brown05dc66a2011-03-02 14:41:58 -0800407void InputReader::fadePointer() {
408 { // acquire device registry reader lock
409 RWLock::AutoRLock _rl(mDeviceRegistryLock);
410
411 for (size_t i = 0; i < mDevices.size(); i++) {
412 InputDevice* device = mDevices.valueAt(i);
413 device->fadePointer();
414 }
415 } // release device registry reader lock
416}
417
Jeff Brown6d0fec22010-07-23 21:28:06 -0700418void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
419 { // acquire state lock
420 AutoMutex _l(mStateLock);
421
422 *outConfiguration = mInputConfiguration;
423 } // release state lock
424}
425
426status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
427 { // acquire device registry reader lock
428 RWLock::AutoRLock _rl(mDeviceRegistryLock);
429
430 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
431 if (deviceIndex < 0) {
432 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700433 }
434
Jeff Brown6d0fec22010-07-23 21:28:06 -0700435 InputDevice* device = mDevices.valueAt(deviceIndex);
436 if (device->isIgnored()) {
437 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700438 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700439
440 device->getDeviceInfo(outDeviceInfo);
441 return OK;
442 } // release device registy reader lock
443}
444
445void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
446 outDeviceIds.clear();
447
448 { // acquire device registry reader lock
449 RWLock::AutoRLock _rl(mDeviceRegistryLock);
450
451 size_t numDevices = mDevices.size();
452 for (size_t i = 0; i < numDevices; i++) {
453 InputDevice* device = mDevices.valueAt(i);
454 if (! device->isIgnored()) {
455 outDeviceIds.add(device->getId());
456 }
457 }
458 } // release device registy reader lock
459}
460
461int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
462 int32_t keyCode) {
463 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
464}
465
466int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
467 int32_t scanCode) {
468 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
469}
470
471int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
472 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
473}
474
475int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
476 GetStateFunc getStateFunc) {
477 { // acquire device registry reader lock
478 RWLock::AutoRLock _rl(mDeviceRegistryLock);
479
480 int32_t result = AKEY_STATE_UNKNOWN;
481 if (deviceId >= 0) {
482 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
483 if (deviceIndex >= 0) {
484 InputDevice* device = mDevices.valueAt(deviceIndex);
485 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
486 result = (device->*getStateFunc)(sourceMask, code);
487 }
488 }
489 } else {
490 size_t numDevices = mDevices.size();
491 for (size_t i = 0; i < numDevices; i++) {
492 InputDevice* device = mDevices.valueAt(i);
493 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
494 result = (device->*getStateFunc)(sourceMask, code);
495 if (result >= AKEY_STATE_DOWN) {
496 return result;
497 }
498 }
499 }
500 }
501 return result;
502 } // release device registy reader lock
503}
504
505bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
506 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
507 memset(outFlags, 0, numCodes);
508 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
509}
510
511bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
512 const int32_t* keyCodes, uint8_t* outFlags) {
513 { // acquire device registry reader lock
514 RWLock::AutoRLock _rl(mDeviceRegistryLock);
515 bool result = false;
516 if (deviceId >= 0) {
517 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
518 if (deviceIndex >= 0) {
519 InputDevice* device = mDevices.valueAt(deviceIndex);
520 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
521 result = device->markSupportedKeyCodes(sourceMask,
522 numCodes, keyCodes, outFlags);
523 }
524 }
525 } else {
526 size_t numDevices = mDevices.size();
527 for (size_t i = 0; i < numDevices; i++) {
528 InputDevice* device = mDevices.valueAt(i);
529 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
530 result |= device->markSupportedKeyCodes(sourceMask,
531 numCodes, keyCodes, outFlags);
532 }
533 }
534 }
535 return result;
536 } // release device registy reader lock
537}
538
Jeff Brownb88102f2010-09-08 11:49:43 -0700539void InputReader::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -0700540 mEventHub->dump(dump);
541 dump.append("\n");
542
543 dump.append("Input Reader State:\n");
544
Jeff Brownef3d7e82010-09-30 14:33:04 -0700545 { // acquire device registry reader lock
546 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700547
Jeff Brownef3d7e82010-09-30 14:33:04 -0700548 for (size_t i = 0; i < mDevices.size(); i++) {
549 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700550 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700551 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700552}
553
Jeff Brown6d0fec22010-07-23 21:28:06 -0700554
555// --- InputReaderThread ---
556
557InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
558 Thread(/*canCallJava*/ true), mReader(reader) {
559}
560
561InputReaderThread::~InputReaderThread() {
562}
563
564bool InputReaderThread::threadLoop() {
565 mReader->loopOnce();
566 return true;
567}
568
569
570// --- InputDevice ---
571
572InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
Jeff Brown56194eb2011-03-02 19:23:13 -0800573 mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700574}
575
576InputDevice::~InputDevice() {
577 size_t numMappers = mMappers.size();
578 for (size_t i = 0; i < numMappers; i++) {
579 delete mMappers[i];
580 }
581 mMappers.clear();
582}
583
Jeff Brownef3d7e82010-09-30 14:33:04 -0700584void InputDevice::dump(String8& dump) {
585 InputDeviceInfo deviceInfo;
586 getDeviceInfo(& deviceInfo);
587
Jeff Brown90655042010-12-02 13:50:46 -0800588 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700589 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800590 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700591 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
592 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800593
594 const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges();
595 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700596 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800597 for (size_t i = 0; i < ranges.size(); i++) {
598 int32_t axis = ranges.keyAt(i);
599 const char* label = getAxisLabel(axis);
600 char name[32];
601 if (label) {
602 strncpy(name, label, sizeof(name));
603 name[sizeof(name) - 1] = '\0';
604 } else {
605 snprintf(name, sizeof(name), "%d", axis);
606 }
607 const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
608 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
609 name, range.min, range.max, range.flat, range.fuzz);
610 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700611 }
612
613 size_t numMappers = mMappers.size();
614 for (size_t i = 0; i < numMappers; i++) {
615 InputMapper* mapper = mMappers[i];
616 mapper->dump(dump);
617 }
618}
619
Jeff Brown6d0fec22010-07-23 21:28:06 -0700620void InputDevice::addMapper(InputMapper* mapper) {
621 mMappers.add(mapper);
622}
623
624void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700625 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800626 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700627 }
628
Jeff Brown6d0fec22010-07-23 21:28:06 -0700629 mSources = 0;
630
631 size_t numMappers = mMappers.size();
632 for (size_t i = 0; i < numMappers; i++) {
633 InputMapper* mapper = mMappers[i];
634 mapper->configure();
635 mSources |= mapper->getSources();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700636 }
637}
638
Jeff Brown6d0fec22010-07-23 21:28:06 -0700639void InputDevice::reset() {
640 size_t numMappers = mMappers.size();
641 for (size_t i = 0; i < numMappers; i++) {
642 InputMapper* mapper = mMappers[i];
643 mapper->reset();
644 }
645}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700646
Jeff Brown6d0fec22010-07-23 21:28:06 -0700647void InputDevice::process(const RawEvent* rawEvent) {
648 size_t numMappers = mMappers.size();
649 for (size_t i = 0; i < numMappers; i++) {
650 InputMapper* mapper = mMappers[i];
651 mapper->process(rawEvent);
652 }
653}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700654
Jeff Brown6d0fec22010-07-23 21:28:06 -0700655void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
656 outDeviceInfo->initialize(mId, mName);
657
658 size_t numMappers = mMappers.size();
659 for (size_t i = 0; i < numMappers; i++) {
660 InputMapper* mapper = mMappers[i];
661 mapper->populateDeviceInfo(outDeviceInfo);
662 }
663}
664
665int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
666 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
667}
668
669int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
670 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
671}
672
673int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
674 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
675}
676
677int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
678 int32_t result = AKEY_STATE_UNKNOWN;
679 size_t numMappers = mMappers.size();
680 for (size_t i = 0; i < numMappers; i++) {
681 InputMapper* mapper = mMappers[i];
682 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
683 result = (mapper->*getStateFunc)(sourceMask, code);
684 if (result >= AKEY_STATE_DOWN) {
685 return result;
686 }
687 }
688 }
689 return result;
690}
691
692bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
693 const int32_t* keyCodes, uint8_t* outFlags) {
694 bool result = false;
695 size_t numMappers = mMappers.size();
696 for (size_t i = 0; i < numMappers; i++) {
697 InputMapper* mapper = mMappers[i];
698 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
699 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
700 }
701 }
702 return result;
703}
704
705int32_t InputDevice::getMetaState() {
706 int32_t result = 0;
707 size_t numMappers = mMappers.size();
708 for (size_t i = 0; i < numMappers; i++) {
709 InputMapper* mapper = mMappers[i];
710 result |= mapper->getMetaState();
711 }
712 return result;
713}
714
Jeff Brown05dc66a2011-03-02 14:41:58 -0800715void InputDevice::fadePointer() {
716 size_t numMappers = mMappers.size();
717 for (size_t i = 0; i < numMappers; i++) {
718 InputMapper* mapper = mMappers[i];
719 mapper->fadePointer();
720 }
721}
722
Jeff Brown6d0fec22010-07-23 21:28:06 -0700723
724// --- InputMapper ---
725
726InputMapper::InputMapper(InputDevice* device) :
727 mDevice(device), mContext(device->getContext()) {
728}
729
730InputMapper::~InputMapper() {
731}
732
733void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
734 info->addSource(getSources());
735}
736
Jeff Brownef3d7e82010-09-30 14:33:04 -0700737void InputMapper::dump(String8& dump) {
738}
739
Jeff Brown6d0fec22010-07-23 21:28:06 -0700740void InputMapper::configure() {
741}
742
743void InputMapper::reset() {
744}
745
746int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
747 return AKEY_STATE_UNKNOWN;
748}
749
750int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
751 return AKEY_STATE_UNKNOWN;
752}
753
754int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
755 return AKEY_STATE_UNKNOWN;
756}
757
758bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
759 const int32_t* keyCodes, uint8_t* outFlags) {
760 return false;
761}
762
763int32_t InputMapper::getMetaState() {
764 return 0;
765}
766
Jeff Brown05dc66a2011-03-02 14:41:58 -0800767void InputMapper::fadePointer() {
768}
769
Jeff Browncb1404e2011-01-15 18:14:15 -0800770void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
771 const RawAbsoluteAxisInfo& axis, const char* name) {
772 if (axis.valid) {
773 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
774 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
775 } else {
776 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
777 }
778}
779
Jeff Brown6d0fec22010-07-23 21:28:06 -0700780
781// --- SwitchInputMapper ---
782
783SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
784 InputMapper(device) {
785}
786
787SwitchInputMapper::~SwitchInputMapper() {
788}
789
790uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800791 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700792}
793
794void SwitchInputMapper::process(const RawEvent* rawEvent) {
795 switch (rawEvent->type) {
796 case EV_SW:
797 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
798 break;
799 }
800}
801
802void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700803 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700804}
805
806int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
807 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
808}
809
810
811// --- KeyboardInputMapper ---
812
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800813KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700814 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800815 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700816 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700817 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700818}
819
820KeyboardInputMapper::~KeyboardInputMapper() {
821}
822
Jeff Brown6328cdc2010-07-29 18:18:33 -0700823void KeyboardInputMapper::initializeLocked() {
824 mLocked.metaState = AMETA_NONE;
825 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700826}
827
828uint32_t KeyboardInputMapper::getSources() {
829 return mSources;
830}
831
832void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
833 InputMapper::populateDeviceInfo(info);
834
835 info->setKeyboardType(mKeyboardType);
836}
837
Jeff Brownef3d7e82010-09-30 14:33:04 -0700838void KeyboardInputMapper::dump(String8& dump) {
839 { // acquire lock
840 AutoMutex _l(mLock);
841 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800842 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700843 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
844 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
845 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
846 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
847 } // release lock
848}
849
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800850
851void KeyboardInputMapper::configure() {
852 InputMapper::configure();
853
854 // Configure basic parameters.
855 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800856
857 // Reset LEDs.
858 {
859 AutoMutex _l(mLock);
860 resetLedStateLocked();
861 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800862}
863
864void KeyboardInputMapper::configureParameters() {
865 mParameters.orientationAware = false;
866 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
867 mParameters.orientationAware);
868
869 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
870}
871
872void KeyboardInputMapper::dumpParameters(String8& dump) {
873 dump.append(INDENT3 "Parameters:\n");
874 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
875 mParameters.associatedDisplayId);
876 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
877 toString(mParameters.orientationAware));
878}
879
Jeff Brown6d0fec22010-07-23 21:28:06 -0700880void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700881 for (;;) {
882 int32_t keyCode, scanCode;
883 { // acquire lock
884 AutoMutex _l(mLock);
885
886 // Synthesize key up event on reset if keys are currently down.
887 if (mLocked.keyDowns.isEmpty()) {
888 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800889 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700890 break; // done
891 }
892
893 const KeyDown& keyDown = mLocked.keyDowns.top();
894 keyCode = keyDown.keyCode;
895 scanCode = keyDown.scanCode;
896 } // release lock
897
Jeff Brown6d0fec22010-07-23 21:28:06 -0700898 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700899 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700900 }
901
902 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700903 getContext()->updateGlobalMetaState();
904}
905
906void KeyboardInputMapper::process(const RawEvent* rawEvent) {
907 switch (rawEvent->type) {
908 case EV_KEY: {
909 int32_t scanCode = rawEvent->scanCode;
910 if (isKeyboardOrGamepadKey(scanCode)) {
911 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
912 rawEvent->flags);
913 }
914 break;
915 }
916 }
917}
918
919bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
920 return scanCode < BTN_MOUSE
921 || scanCode >= KEY_OK
Jeff Browncb1404e2011-01-15 18:14:15 -0800922 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700923}
924
Jeff Brown6328cdc2010-07-29 18:18:33 -0700925void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
926 int32_t scanCode, uint32_t policyFlags) {
927 int32_t newMetaState;
928 nsecs_t downTime;
929 bool metaStateChanged = false;
930
931 { // acquire lock
932 AutoMutex _l(mLock);
933
934 if (down) {
935 // Rotate key codes according to orientation if needed.
936 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800937 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700938 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800939 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
940 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800941 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700942 }
943
944 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700945 }
946
Jeff Brown6328cdc2010-07-29 18:18:33 -0700947 // Add key down.
948 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
949 if (keyDownIndex >= 0) {
950 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800951 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700952 } else {
953 // key down
Jeff Brownfe508922011-01-18 15:10:10 -0800954 if ((policyFlags & POLICY_FLAG_VIRTUAL)
955 && mContext->shouldDropVirtualKey(when,
956 getDevice(), keyCode, scanCode)) {
957 return;
958 }
959
Jeff Brown6328cdc2010-07-29 18:18:33 -0700960 mLocked.keyDowns.push();
961 KeyDown& keyDown = mLocked.keyDowns.editTop();
962 keyDown.keyCode = keyCode;
963 keyDown.scanCode = scanCode;
964 }
965
966 mLocked.downTime = when;
967 } else {
968 // Remove key down.
969 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
970 if (keyDownIndex >= 0) {
971 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800972 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700973 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
974 } else {
975 // key was not actually down
976 LOGI("Dropping key up from device %s because the key was not down. "
977 "keyCode=%d, scanCode=%d",
978 getDeviceName().string(), keyCode, scanCode);
979 return;
980 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700981 }
982
Jeff Brown6328cdc2010-07-29 18:18:33 -0700983 int32_t oldMetaState = mLocked.metaState;
984 newMetaState = updateMetaState(keyCode, down, oldMetaState);
985 if (oldMetaState != newMetaState) {
986 mLocked.metaState = newMetaState;
987 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -0700988 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700989 }
Jeff Brownfd0358292010-06-30 16:10:35 -0700990
Jeff Brown6328cdc2010-07-29 18:18:33 -0700991 downTime = mLocked.downTime;
992 } // release lock
993
Jeff Brown56194eb2011-03-02 19:23:13 -0800994 // Key down on external an keyboard should wake the device.
995 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
996 // For internal keyboards, the key layout file should specify the policy flags for
997 // each wake key individually.
998 // TODO: Use the input device configuration to control this behavior more finely.
999 if (down && getDevice()->isExternal()
1000 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1001 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1002 }
1003
Jeff Brown6328cdc2010-07-29 18:18:33 -07001004 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001005 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001006 }
1007
Jeff Brown05dc66a2011-03-02 14:41:58 -08001008 if (down && !isMetaKey(keyCode)) {
1009 getContext()->fadePointer();
1010 }
1011
Jeff Brown83c09682010-12-23 17:50:18 -08001012 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001013 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1014 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001015}
1016
Jeff Brown6328cdc2010-07-29 18:18:33 -07001017ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1018 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001019 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001020 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001021 return i;
1022 }
1023 }
1024 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001025}
1026
Jeff Brown6d0fec22010-07-23 21:28:06 -07001027int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1028 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1029}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001030
Jeff Brown6d0fec22010-07-23 21:28:06 -07001031int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1032 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1033}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001034
Jeff Brown6d0fec22010-07-23 21:28:06 -07001035bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1036 const int32_t* keyCodes, uint8_t* outFlags) {
1037 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1038}
1039
1040int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001041 { // acquire lock
1042 AutoMutex _l(mLock);
1043 return mLocked.metaState;
1044 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001045}
1046
Jeff Brown49ed71d2010-12-06 17:13:33 -08001047void KeyboardInputMapper::resetLedStateLocked() {
1048 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1049 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1050 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1051
1052 updateLedStateLocked(true);
1053}
1054
1055void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1056 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1057 ledState.on = false;
1058}
1059
Jeff Brown497a92c2010-09-12 17:55:08 -07001060void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1061 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001062 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001063 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001064 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001065 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001066 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001067}
1068
1069void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1070 int32_t led, int32_t modifier, bool reset) {
1071 if (ledState.avail) {
1072 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001073 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001074 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1075 ledState.on = desiredState;
1076 }
1077 }
1078}
1079
Jeff Brown6d0fec22010-07-23 21:28:06 -07001080
Jeff Brown83c09682010-12-23 17:50:18 -08001081// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001082
Jeff Brown83c09682010-12-23 17:50:18 -08001083CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001084 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001085 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001086}
1087
Jeff Brown83c09682010-12-23 17:50:18 -08001088CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001089}
1090
Jeff Brown83c09682010-12-23 17:50:18 -08001091uint32_t CursorInputMapper::getSources() {
1092 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001093}
1094
Jeff Brown83c09682010-12-23 17:50:18 -08001095void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001096 InputMapper::populateDeviceInfo(info);
1097
Jeff Brown83c09682010-12-23 17:50:18 -08001098 if (mParameters.mode == Parameters::MODE_POINTER) {
1099 float minX, minY, maxX, maxY;
1100 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001101 info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
1102 info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001103 }
1104 } else {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001105 info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
1106 info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001107 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001108 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
1109
1110 if (mHaveVWheel) {
1111 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1112 }
1113 if (mHaveHWheel) {
1114 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1115 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001116}
1117
Jeff Brown83c09682010-12-23 17:50:18 -08001118void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001119 { // acquire lock
1120 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001121 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001122 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001123 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1124 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001125 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1126 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001127 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1128 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1129 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1130 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001131 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1132 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1133 } // release lock
1134}
1135
Jeff Brown83c09682010-12-23 17:50:18 -08001136void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001137 InputMapper::configure();
1138
1139 // Configure basic parameters.
1140 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001141
1142 // Configure device mode.
1143 switch (mParameters.mode) {
1144 case Parameters::MODE_POINTER:
1145 mSources = AINPUT_SOURCE_MOUSE;
1146 mXPrecision = 1.0f;
1147 mYPrecision = 1.0f;
1148 mXScale = 1.0f;
1149 mYScale = 1.0f;
1150 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1151 break;
1152 case Parameters::MODE_NAVIGATION:
1153 mSources = AINPUT_SOURCE_TRACKBALL;
1154 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1155 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1156 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1157 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1158 break;
1159 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001160
1161 mVWheelScale = 1.0f;
1162 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001163
1164 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1165 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001166}
1167
Jeff Brown83c09682010-12-23 17:50:18 -08001168void CursorInputMapper::configureParameters() {
1169 mParameters.mode = Parameters::MODE_POINTER;
1170 String8 cursorModeString;
1171 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1172 if (cursorModeString == "navigation") {
1173 mParameters.mode = Parameters::MODE_NAVIGATION;
1174 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1175 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1176 }
1177 }
1178
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001179 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001180 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001181 mParameters.orientationAware);
1182
Jeff Brown83c09682010-12-23 17:50:18 -08001183 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1184 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001185}
1186
Jeff Brown83c09682010-12-23 17:50:18 -08001187void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001188 dump.append(INDENT3 "Parameters:\n");
1189 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1190 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001191
1192 switch (mParameters.mode) {
1193 case Parameters::MODE_POINTER:
1194 dump.append(INDENT4 "Mode: pointer\n");
1195 break;
1196 case Parameters::MODE_NAVIGATION:
1197 dump.append(INDENT4 "Mode: navigation\n");
1198 break;
1199 default:
1200 assert(false);
1201 }
1202
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001203 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1204 toString(mParameters.orientationAware));
1205}
1206
Jeff Brown83c09682010-12-23 17:50:18 -08001207void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001208 mAccumulator.clear();
1209
Jeff Brown6328cdc2010-07-29 18:18:33 -07001210 mLocked.down = false;
1211 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001212}
1213
Jeff Brown83c09682010-12-23 17:50:18 -08001214void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001215 for (;;) {
1216 { // acquire lock
1217 AutoMutex _l(mLock);
1218
1219 if (! mLocked.down) {
1220 initializeLocked();
1221 break; // done
1222 }
1223 } // release lock
1224
Jeff Brown83c09682010-12-23 17:50:18 -08001225 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001226 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001227 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001228 mAccumulator.btnMouse = false;
1229 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001230 }
1231
Jeff Brown6d0fec22010-07-23 21:28:06 -07001232 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001233}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001234
Jeff Brown83c09682010-12-23 17:50:18 -08001235void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001236 switch (rawEvent->type) {
1237 case EV_KEY:
1238 switch (rawEvent->scanCode) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001239 case BTN_LEFT:
1240 case BTN_RIGHT:
1241 case BTN_MIDDLE:
1242 case BTN_SIDE:
1243 case BTN_EXTRA:
1244 case BTN_FORWARD:
1245 case BTN_BACK:
1246 case BTN_TASK:
Jeff Brown6d0fec22010-07-23 21:28:06 -07001247 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1248 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001249 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1250 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001251 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001252 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001253 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001254 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001255
Jeff Brown6d0fec22010-07-23 21:28:06 -07001256 case EV_REL:
1257 switch (rawEvent->scanCode) {
1258 case REL_X:
1259 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1260 mAccumulator.relX = rawEvent->value;
1261 break;
1262 case REL_Y:
1263 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1264 mAccumulator.relY = rawEvent->value;
1265 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001266 case REL_WHEEL:
1267 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1268 mAccumulator.relWheel = rawEvent->value;
1269 break;
1270 case REL_HWHEEL:
1271 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1272 mAccumulator.relHWheel = rawEvent->value;
1273 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001274 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001275 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001276
Jeff Brown6d0fec22010-07-23 21:28:06 -07001277 case EV_SYN:
1278 switch (rawEvent->scanCode) {
1279 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001280 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001281 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001282 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001283 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001284 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001285}
1286
Jeff Brown83c09682010-12-23 17:50:18 -08001287void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001288 uint32_t fields = mAccumulator.fields;
1289 if (fields == 0) {
1290 return; // no new state changes, so nothing to do
1291 }
1292
Jeff Brown6328cdc2010-07-29 18:18:33 -07001293 int motionEventAction;
1294 PointerCoords pointerCoords;
1295 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001296 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001297 { // acquire lock
1298 AutoMutex _l(mLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001299
Jeff Brown6328cdc2010-07-29 18:18:33 -07001300 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1301
1302 if (downChanged) {
1303 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001304 if (!mLocked.down) {
1305 mLocked.down = true;
1306 mLocked.downTime = when;
1307 } else {
1308 downChanged = false;
1309 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001310 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001311 if (mLocked.down) {
1312 mLocked.down = false;
1313 } else {
1314 downChanged = false;
1315 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001316 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001317 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001318
Jeff Brown6328cdc2010-07-29 18:18:33 -07001319 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001320 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1321 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001322
Jeff Brown6328cdc2010-07-29 18:18:33 -07001323 if (downChanged) {
1324 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browncc0c1592011-02-19 05:07:28 -08001325 } else if (mLocked.down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001326 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001327 } else {
1328 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001329 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001330
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001331 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001332 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001333 // Rotate motion based on display orientation if needed.
1334 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1335 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001336 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1337 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001338 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001339 }
1340
1341 float temp;
1342 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001343 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001344 temp = deltaX;
1345 deltaX = deltaY;
1346 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001347 break;
1348
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001349 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001350 deltaX = -deltaX;
1351 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001352 break;
1353
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001354 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001355 temp = deltaX;
1356 deltaX = -deltaY;
1357 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001358 break;
1359 }
1360 }
Jeff Brown83c09682010-12-23 17:50:18 -08001361
Jeff Brown91c69ab2011-02-14 17:03:18 -08001362 pointerCoords.clear();
1363
Jeff Brown83c09682010-12-23 17:50:18 -08001364 if (mPointerController != NULL) {
1365 mPointerController->move(deltaX, deltaY);
1366 if (downChanged) {
1367 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1368 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08001369 float x, y;
1370 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001371 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1372 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown83c09682010-12-23 17:50:18 -08001373 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001374 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1375 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001376 }
1377
Jeff Brownebbd5d12011-02-17 13:01:34 -08001378 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001379
1380 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001381 vscroll = mAccumulator.relWheel;
1382 } else {
1383 vscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001384 }
1385 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001386 hscroll = mAccumulator.relHWheel;
1387 } else {
1388 hscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001389 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001390 if (hscroll != 0 || vscroll != 0) {
1391 mPointerController->unfade();
1392 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001393 } // release lock
1394
Jeff Brown56194eb2011-03-02 19:23:13 -08001395 // Moving an external trackball or mouse should wake the device.
1396 // We don't do this for internal cursor devices to prevent them from waking up
1397 // the device in your pocket.
1398 // TODO: Use the input device configuration to control this behavior more finely.
1399 uint32_t policyFlags = 0;
1400 if (getDevice()->isExternal()) {
1401 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1402 }
1403
Jeff Brown6d0fec22010-07-23 21:28:06 -07001404 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001405 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08001406 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07001407 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001408 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1409
1410 mAccumulator.clear();
Jeff Brown33bbfd22011-02-24 20:55:35 -08001411
1412 if (vscroll != 0 || hscroll != 0) {
1413 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1414 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1415
Jeff Brown56194eb2011-03-02 19:23:13 -08001416 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown33bbfd22011-02-24 20:55:35 -08001417 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1418 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1419 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001420}
1421
Jeff Brown83c09682010-12-23 17:50:18 -08001422int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001423 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1424 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1425 } else {
1426 return AKEY_STATE_UNKNOWN;
1427 }
1428}
1429
Jeff Brown05dc66a2011-03-02 14:41:58 -08001430void CursorInputMapper::fadePointer() {
1431 { // acquire lock
1432 AutoMutex _l(mLock);
1433 mPointerController->fade();
1434 } // release lock
1435}
1436
Jeff Brown6d0fec22010-07-23 21:28:06 -07001437
1438// --- TouchInputMapper ---
1439
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001440TouchInputMapper::TouchInputMapper(InputDevice* device) :
1441 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001442 mLocked.surfaceOrientation = -1;
1443 mLocked.surfaceWidth = -1;
1444 mLocked.surfaceHeight = -1;
1445
1446 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001447}
1448
1449TouchInputMapper::~TouchInputMapper() {
1450}
1451
1452uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001453 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001454}
1455
1456void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1457 InputMapper::populateDeviceInfo(info);
1458
Jeff Brown6328cdc2010-07-29 18:18:33 -07001459 { // acquire lock
1460 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001461
Jeff Brown6328cdc2010-07-29 18:18:33 -07001462 // Ensure surface information is up to date so that orientation changes are
1463 // noticed immediately.
1464 configureSurfaceLocked();
1465
Jeff Brown6f2fba42011-02-19 01:08:02 -08001466 info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1467 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001468
1469 if (mLocked.orientedRanges.havePressure) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001470 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown8d608662010-08-30 03:02:23 -07001471 mLocked.orientedRanges.pressure);
1472 }
1473
1474 if (mLocked.orientedRanges.haveSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001475 info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown8d608662010-08-30 03:02:23 -07001476 mLocked.orientedRanges.size);
1477 }
1478
Jeff Brownc6d282b2010-10-14 21:42:15 -07001479 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001480 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001481 mLocked.orientedRanges.touchMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001482 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001483 mLocked.orientedRanges.touchMinor);
1484 }
1485
Jeff Brownc6d282b2010-10-14 21:42:15 -07001486 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001487 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001488 mLocked.orientedRanges.toolMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001489 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001490 mLocked.orientedRanges.toolMinor);
1491 }
1492
1493 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001494 info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown8d608662010-08-30 03:02:23 -07001495 mLocked.orientedRanges.orientation);
1496 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001497 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001498}
1499
Jeff Brownef3d7e82010-09-30 14:33:04 -07001500void TouchInputMapper::dump(String8& dump) {
1501 { // acquire lock
1502 AutoMutex _l(mLock);
1503 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001504 dumpParameters(dump);
1505 dumpVirtualKeysLocked(dump);
1506 dumpRawAxes(dump);
1507 dumpCalibration(dump);
1508 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001509 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001510 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1511 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1512 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1513 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1514 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1515 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1516 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1517 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1518 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1519 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1520 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1521 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1522 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1523 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001524 } // release lock
1525}
1526
Jeff Brown6328cdc2010-07-29 18:18:33 -07001527void TouchInputMapper::initializeLocked() {
1528 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001529 mLastTouch.clear();
1530 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001531
1532 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1533 mAveragingTouchFilter.historyStart[i] = 0;
1534 mAveragingTouchFilter.historyEnd[i] = 0;
1535 }
1536
1537 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001538
1539 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001540
1541 mLocked.orientedRanges.havePressure = false;
1542 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001543 mLocked.orientedRanges.haveTouchSize = false;
1544 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001545 mLocked.orientedRanges.haveOrientation = false;
1546}
1547
Jeff Brown6d0fec22010-07-23 21:28:06 -07001548void TouchInputMapper::configure() {
1549 InputMapper::configure();
1550
1551 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001552 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001553
Jeff Brown83c09682010-12-23 17:50:18 -08001554 // Configure sources.
1555 switch (mParameters.deviceType) {
1556 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1557 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1558 break;
1559 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1560 mSources = AINPUT_SOURCE_TOUCHPAD;
1561 break;
1562 default:
1563 assert(false);
1564 }
1565
Jeff Brown6d0fec22010-07-23 21:28:06 -07001566 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001567 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001568
1569 // Prepare input device calibration.
1570 parseCalibration();
1571 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001572
Jeff Brown6328cdc2010-07-29 18:18:33 -07001573 { // acquire lock
1574 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001575
Jeff Brown8d608662010-08-30 03:02:23 -07001576 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001577 configureSurfaceLocked();
1578 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001579}
1580
Jeff Brown8d608662010-08-30 03:02:23 -07001581void TouchInputMapper::configureParameters() {
1582 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1583 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1584 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001585 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001586
1587 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001588 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001589 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1590 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001591 if (deviceTypeString == "touchScreen") {
1592 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1593 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001594 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1595 }
1596 }
1597 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1598
1599 mParameters.orientationAware = isTouchScreen;
1600 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1601 mParameters.orientationAware);
1602
1603 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001604}
1605
Jeff Brownef3d7e82010-09-30 14:33:04 -07001606void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001607 dump.append(INDENT3 "Parameters:\n");
1608
1609 switch (mParameters.deviceType) {
1610 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1611 dump.append(INDENT4 "DeviceType: touchScreen\n");
1612 break;
1613 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1614 dump.append(INDENT4 "DeviceType: touchPad\n");
1615 break;
1616 default:
1617 assert(false);
1618 }
1619
1620 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1621 mParameters.associatedDisplayId);
1622 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1623 toString(mParameters.orientationAware));
1624
1625 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001626 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001627 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001628 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001629 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001630 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001631}
1632
Jeff Brown8d608662010-08-30 03:02:23 -07001633void TouchInputMapper::configureRawAxes() {
1634 mRawAxes.x.clear();
1635 mRawAxes.y.clear();
1636 mRawAxes.pressure.clear();
1637 mRawAxes.touchMajor.clear();
1638 mRawAxes.touchMinor.clear();
1639 mRawAxes.toolMajor.clear();
1640 mRawAxes.toolMinor.clear();
1641 mRawAxes.orientation.clear();
1642}
1643
Jeff Brownef3d7e82010-09-30 14:33:04 -07001644void TouchInputMapper::dumpRawAxes(String8& dump) {
1645 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001646 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1647 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1648 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1649 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1650 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1651 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1652 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1653 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001654}
1655
Jeff Brown6328cdc2010-07-29 18:18:33 -07001656bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001657 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001658 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001659 int32_t width = mRawAxes.x.getRange();
1660 int32_t height = mRawAxes.y.getRange();
1661
1662 if (mParameters.associatedDisplayId >= 0) {
1663 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1664 bool wantOrientation = mParameters.orientationAware;
1665
Jeff Brown6328cdc2010-07-29 18:18:33 -07001666 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001667 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1668 wantSize ? &width : NULL, wantSize ? &height : NULL,
1669 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001670 return false;
1671 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001672 }
1673
Jeff Brown6328cdc2010-07-29 18:18:33 -07001674 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001675 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001676 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001677 }
1678
Jeff Brown6328cdc2010-07-29 18:18:33 -07001679 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001680 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001681 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001682 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001683
Jeff Brown6328cdc2010-07-29 18:18:33 -07001684 mLocked.surfaceWidth = width;
1685 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001686
Jeff Brown8d608662010-08-30 03:02:23 -07001687 // Configure X and Y factors.
1688 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001689 mLocked.xOrigin = mCalibration.haveXOrigin
1690 ? mCalibration.xOrigin
1691 : mRawAxes.x.minValue;
1692 mLocked.yOrigin = mCalibration.haveYOrigin
1693 ? mCalibration.yOrigin
1694 : mRawAxes.y.minValue;
1695 mLocked.xScale = mCalibration.haveXScale
1696 ? mCalibration.xScale
1697 : float(width) / mRawAxes.x.getRange();
1698 mLocked.yScale = mCalibration.haveYScale
1699 ? mCalibration.yScale
1700 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001701 mLocked.xPrecision = 1.0f / mLocked.xScale;
1702 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001703
Jeff Brown6328cdc2010-07-29 18:18:33 -07001704 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001705 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001706 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001707 mLocked.xOrigin = 0;
1708 mLocked.yOrigin = 0;
1709 mLocked.xScale = 1.0f;
1710 mLocked.yScale = 1.0f;
1711 mLocked.xPrecision = 1.0f;
1712 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001713 }
1714
Jeff Brown8d608662010-08-30 03:02:23 -07001715 // Scale factor for terms that are not oriented in a particular axis.
1716 // If the pixels are square then xScale == yScale otherwise we fake it
1717 // by choosing an average.
1718 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001719
Jeff Brown8d608662010-08-30 03:02:23 -07001720 // Size of diagonal axis.
1721 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001722
Jeff Brown8d608662010-08-30 03:02:23 -07001723 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001724 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1725 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001726 mLocked.orientedRanges.touchMajor.min = 0;
1727 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1728 mLocked.orientedRanges.touchMajor.flat = 0;
1729 mLocked.orientedRanges.touchMajor.fuzz = 0;
1730 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1731 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001732
Jeff Brown8d608662010-08-30 03:02:23 -07001733 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001734 mLocked.toolSizeLinearScale = 0;
1735 mLocked.toolSizeLinearBias = 0;
1736 mLocked.toolSizeAreaScale = 0;
1737 mLocked.toolSizeAreaBias = 0;
1738 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1739 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1740 if (mCalibration.haveToolSizeLinearScale) {
1741 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001742 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001743 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001744 / mRawAxes.toolMajor.maxValue;
1745 }
1746
Jeff Brownc6d282b2010-10-14 21:42:15 -07001747 if (mCalibration.haveToolSizeLinearBias) {
1748 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1749 }
1750 } else if (mCalibration.toolSizeCalibration ==
1751 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1752 if (mCalibration.haveToolSizeLinearScale) {
1753 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1754 } else {
1755 mLocked.toolSizeLinearScale = min(width, height);
1756 }
1757
1758 if (mCalibration.haveToolSizeLinearBias) {
1759 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1760 }
1761
1762 if (mCalibration.haveToolSizeAreaScale) {
1763 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1764 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1765 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1766 }
1767
1768 if (mCalibration.haveToolSizeAreaBias) {
1769 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001770 }
1771 }
1772
Jeff Brownc6d282b2010-10-14 21:42:15 -07001773 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001774 mLocked.orientedRanges.toolMajor.min = 0;
1775 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1776 mLocked.orientedRanges.toolMajor.flat = 0;
1777 mLocked.orientedRanges.toolMajor.fuzz = 0;
1778 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1779 }
1780
1781 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001782 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001783 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1784 RawAbsoluteAxisInfo rawPressureAxis;
1785 switch (mCalibration.pressureSource) {
1786 case Calibration::PRESSURE_SOURCE_PRESSURE:
1787 rawPressureAxis = mRawAxes.pressure;
1788 break;
1789 case Calibration::PRESSURE_SOURCE_TOUCH:
1790 rawPressureAxis = mRawAxes.touchMajor;
1791 break;
1792 default:
1793 rawPressureAxis.clear();
1794 }
1795
Jeff Brown8d608662010-08-30 03:02:23 -07001796 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1797 || mCalibration.pressureCalibration
1798 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1799 if (mCalibration.havePressureScale) {
1800 mLocked.pressureScale = mCalibration.pressureScale;
1801 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1802 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1803 }
1804 }
1805
1806 mLocked.orientedRanges.havePressure = true;
1807 mLocked.orientedRanges.pressure.min = 0;
1808 mLocked.orientedRanges.pressure.max = 1.0;
1809 mLocked.orientedRanges.pressure.flat = 0;
1810 mLocked.orientedRanges.pressure.fuzz = 0;
1811 }
1812
1813 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001814 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001815 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001816 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1817 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1818 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1819 }
1820 }
1821
1822 mLocked.orientedRanges.haveSize = true;
1823 mLocked.orientedRanges.size.min = 0;
1824 mLocked.orientedRanges.size.max = 1.0;
1825 mLocked.orientedRanges.size.flat = 0;
1826 mLocked.orientedRanges.size.fuzz = 0;
1827 }
1828
1829 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001830 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001831 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001832 if (mCalibration.orientationCalibration
1833 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1834 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1835 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1836 }
1837 }
1838
1839 mLocked.orientedRanges.orientation.min = - M_PI_2;
1840 mLocked.orientedRanges.orientation.max = M_PI_2;
1841 mLocked.orientedRanges.orientation.flat = 0;
1842 mLocked.orientedRanges.orientation.fuzz = 0;
1843 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001844 }
1845
1846 if (orientationChanged || sizeChanged) {
1847 // Compute oriented surface dimensions, precision, and scales.
1848 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001849 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001850 case DISPLAY_ORIENTATION_90:
1851 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001852 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1853 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1854 mLocked.orientedXPrecision = mLocked.yPrecision;
1855 mLocked.orientedYPrecision = mLocked.xPrecision;
1856 orientedXScale = mLocked.yScale;
1857 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001858 break;
1859 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001860 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1861 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1862 mLocked.orientedXPrecision = mLocked.xPrecision;
1863 mLocked.orientedYPrecision = mLocked.yPrecision;
1864 orientedXScale = mLocked.xScale;
1865 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001866 break;
1867 }
1868
1869 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001870 mLocked.orientedRanges.x.min = 0;
1871 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1872 mLocked.orientedRanges.x.flat = 0;
1873 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001874
Jeff Brown6328cdc2010-07-29 18:18:33 -07001875 mLocked.orientedRanges.y.min = 0;
1876 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1877 mLocked.orientedRanges.y.flat = 0;
1878 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001879 }
1880
1881 return true;
1882}
1883
Jeff Brownef3d7e82010-09-30 14:33:04 -07001884void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1885 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1886 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1887 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001888}
1889
Jeff Brown6328cdc2010-07-29 18:18:33 -07001890void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001891 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001892
Jeff Brown8d608662010-08-30 03:02:23 -07001893 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001894 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001895
Jeff Brown6328cdc2010-07-29 18:18:33 -07001896 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001897
Jeff Brown6328cdc2010-07-29 18:18:33 -07001898 if (virtualKeyDefinitions.size() == 0) {
1899 return;
1900 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001901
Jeff Brown6328cdc2010-07-29 18:18:33 -07001902 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1903
Jeff Brown8d608662010-08-30 03:02:23 -07001904 int32_t touchScreenLeft = mRawAxes.x.minValue;
1905 int32_t touchScreenTop = mRawAxes.y.minValue;
1906 int32_t touchScreenWidth = mRawAxes.x.getRange();
1907 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001908
1909 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001910 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001911 virtualKeyDefinitions[i];
1912
1913 mLocked.virtualKeys.add();
1914 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1915
1916 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1917 int32_t keyCode;
1918 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001919 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001920 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001921 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1922 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001923 mLocked.virtualKeys.pop(); // drop the key
1924 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001925 }
1926
Jeff Brown6328cdc2010-07-29 18:18:33 -07001927 virtualKey.keyCode = keyCode;
1928 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001929
Jeff Brown6328cdc2010-07-29 18:18:33 -07001930 // convert the key definition's display coordinates into touch coordinates for a hit box
1931 int32_t halfWidth = virtualKeyDefinition.width / 2;
1932 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001933
Jeff Brown6328cdc2010-07-29 18:18:33 -07001934 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1935 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1936 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1937 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1938 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1939 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1940 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1941 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001942
Jeff Brownef3d7e82010-09-30 14:33:04 -07001943 }
1944}
1945
1946void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1947 if (!mLocked.virtualKeys.isEmpty()) {
1948 dump.append(INDENT3 "Virtual Keys:\n");
1949
1950 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1951 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1952 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1953 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1954 i, virtualKey.scanCode, virtualKey.keyCode,
1955 virtualKey.hitLeft, virtualKey.hitRight,
1956 virtualKey.hitTop, virtualKey.hitBottom);
1957 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001958 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001959}
1960
Jeff Brown8d608662010-08-30 03:02:23 -07001961void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001962 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001963 Calibration& out = mCalibration;
1964
Jeff Brown511ee5f2010-10-18 13:32:20 -07001965 // Position
1966 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1967 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1968 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1969 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1970
Jeff Brownc6d282b2010-10-14 21:42:15 -07001971 // Touch Size
1972 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1973 String8 touchSizeCalibrationString;
1974 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1975 if (touchSizeCalibrationString == "none") {
1976 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1977 } else if (touchSizeCalibrationString == "geometric") {
1978 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1979 } else if (touchSizeCalibrationString == "pressure") {
1980 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1981 } else if (touchSizeCalibrationString != "default") {
1982 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1983 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001984 }
1985 }
1986
Jeff Brownc6d282b2010-10-14 21:42:15 -07001987 // Tool Size
1988 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1989 String8 toolSizeCalibrationString;
1990 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1991 if (toolSizeCalibrationString == "none") {
1992 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1993 } else if (toolSizeCalibrationString == "geometric") {
1994 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1995 } else if (toolSizeCalibrationString == "linear") {
1996 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1997 } else if (toolSizeCalibrationString == "area") {
1998 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1999 } else if (toolSizeCalibrationString != "default") {
2000 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2001 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002002 }
2003 }
2004
Jeff Brownc6d282b2010-10-14 21:42:15 -07002005 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2006 out.toolSizeLinearScale);
2007 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2008 out.toolSizeLinearBias);
2009 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2010 out.toolSizeAreaScale);
2011 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2012 out.toolSizeAreaBias);
2013 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2014 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07002015
2016 // Pressure
2017 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2018 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002019 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002020 if (pressureCalibrationString == "none") {
2021 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2022 } else if (pressureCalibrationString == "physical") {
2023 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2024 } else if (pressureCalibrationString == "amplitude") {
2025 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2026 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002027 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002028 pressureCalibrationString.string());
2029 }
2030 }
2031
2032 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2033 String8 pressureSourceString;
2034 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2035 if (pressureSourceString == "pressure") {
2036 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2037 } else if (pressureSourceString == "touch") {
2038 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2039 } else if (pressureSourceString != "default") {
2040 LOGW("Invalid value for touch.pressure.source: '%s'",
2041 pressureSourceString.string());
2042 }
2043 }
2044
2045 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2046 out.pressureScale);
2047
2048 // Size
2049 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2050 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002051 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002052 if (sizeCalibrationString == "none") {
2053 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2054 } else if (sizeCalibrationString == "normalized") {
2055 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2056 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002057 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002058 sizeCalibrationString.string());
2059 }
2060 }
2061
2062 // Orientation
2063 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2064 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002065 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002066 if (orientationCalibrationString == "none") {
2067 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2068 } else if (orientationCalibrationString == "interpolated") {
2069 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002070 } else if (orientationCalibrationString == "vector") {
2071 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002072 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002073 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002074 orientationCalibrationString.string());
2075 }
2076 }
2077}
2078
2079void TouchInputMapper::resolveCalibration() {
2080 // Pressure
2081 switch (mCalibration.pressureSource) {
2082 case Calibration::PRESSURE_SOURCE_DEFAULT:
2083 if (mRawAxes.pressure.valid) {
2084 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2085 } else if (mRawAxes.touchMajor.valid) {
2086 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2087 }
2088 break;
2089
2090 case Calibration::PRESSURE_SOURCE_PRESSURE:
2091 if (! mRawAxes.pressure.valid) {
2092 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2093 "the pressure axis is not available.");
2094 }
2095 break;
2096
2097 case Calibration::PRESSURE_SOURCE_TOUCH:
2098 if (! mRawAxes.touchMajor.valid) {
2099 LOGW("Calibration property touch.pressure.source is 'touch' but "
2100 "the touchMajor axis is not available.");
2101 }
2102 break;
2103
2104 default:
2105 break;
2106 }
2107
2108 switch (mCalibration.pressureCalibration) {
2109 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2110 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2111 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2112 } else {
2113 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2114 }
2115 break;
2116
2117 default:
2118 break;
2119 }
2120
Jeff Brownc6d282b2010-10-14 21:42:15 -07002121 // Tool Size
2122 switch (mCalibration.toolSizeCalibration) {
2123 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002124 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002125 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002126 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002127 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002128 }
2129 break;
2130
2131 default:
2132 break;
2133 }
2134
Jeff Brownc6d282b2010-10-14 21:42:15 -07002135 // Touch Size
2136 switch (mCalibration.touchSizeCalibration) {
2137 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002138 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002139 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2140 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002141 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002142 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002143 }
2144 break;
2145
2146 default:
2147 break;
2148 }
2149
2150 // Size
2151 switch (mCalibration.sizeCalibration) {
2152 case Calibration::SIZE_CALIBRATION_DEFAULT:
2153 if (mRawAxes.toolMajor.valid) {
2154 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2155 } else {
2156 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2157 }
2158 break;
2159
2160 default:
2161 break;
2162 }
2163
2164 // Orientation
2165 switch (mCalibration.orientationCalibration) {
2166 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2167 if (mRawAxes.orientation.valid) {
2168 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2169 } else {
2170 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2171 }
2172 break;
2173
2174 default:
2175 break;
2176 }
2177}
2178
Jeff Brownef3d7e82010-09-30 14:33:04 -07002179void TouchInputMapper::dumpCalibration(String8& dump) {
2180 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002181
Jeff Brown511ee5f2010-10-18 13:32:20 -07002182 // Position
2183 if (mCalibration.haveXOrigin) {
2184 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2185 }
2186 if (mCalibration.haveYOrigin) {
2187 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2188 }
2189 if (mCalibration.haveXScale) {
2190 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2191 }
2192 if (mCalibration.haveYScale) {
2193 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2194 }
2195
Jeff Brownc6d282b2010-10-14 21:42:15 -07002196 // Touch Size
2197 switch (mCalibration.touchSizeCalibration) {
2198 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2199 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002200 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002201 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2202 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002203 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002204 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2205 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002206 break;
2207 default:
2208 assert(false);
2209 }
2210
Jeff Brownc6d282b2010-10-14 21:42:15 -07002211 // Tool Size
2212 switch (mCalibration.toolSizeCalibration) {
2213 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2214 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002215 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002216 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2217 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002218 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002219 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2220 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2221 break;
2222 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2223 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002224 break;
2225 default:
2226 assert(false);
2227 }
2228
Jeff Brownc6d282b2010-10-14 21:42:15 -07002229 if (mCalibration.haveToolSizeLinearScale) {
2230 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2231 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002232 }
2233
Jeff Brownc6d282b2010-10-14 21:42:15 -07002234 if (mCalibration.haveToolSizeLinearBias) {
2235 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2236 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002237 }
2238
Jeff Brownc6d282b2010-10-14 21:42:15 -07002239 if (mCalibration.haveToolSizeAreaScale) {
2240 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2241 mCalibration.toolSizeAreaScale);
2242 }
2243
2244 if (mCalibration.haveToolSizeAreaBias) {
2245 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2246 mCalibration.toolSizeAreaBias);
2247 }
2248
2249 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002250 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002251 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002252 }
2253
2254 // Pressure
2255 switch (mCalibration.pressureCalibration) {
2256 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002257 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002258 break;
2259 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002260 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002261 break;
2262 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002263 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002264 break;
2265 default:
2266 assert(false);
2267 }
2268
2269 switch (mCalibration.pressureSource) {
2270 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002271 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002272 break;
2273 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002274 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002275 break;
2276 case Calibration::PRESSURE_SOURCE_DEFAULT:
2277 break;
2278 default:
2279 assert(false);
2280 }
2281
2282 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002283 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2284 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002285 }
2286
2287 // Size
2288 switch (mCalibration.sizeCalibration) {
2289 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002290 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002291 break;
2292 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002293 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002294 break;
2295 default:
2296 assert(false);
2297 }
2298
2299 // Orientation
2300 switch (mCalibration.orientationCalibration) {
2301 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002302 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002303 break;
2304 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002305 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002306 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002307 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2308 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2309 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002310 default:
2311 assert(false);
2312 }
2313}
2314
Jeff Brown6d0fec22010-07-23 21:28:06 -07002315void TouchInputMapper::reset() {
2316 // Synthesize touch up event if touch is currently down.
2317 // This will also take care of finishing virtual key processing if needed.
2318 if (mLastTouch.pointerCount != 0) {
2319 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2320 mCurrentTouch.clear();
2321 syncTouch(when, true);
2322 }
2323
Jeff Brown6328cdc2010-07-29 18:18:33 -07002324 { // acquire lock
2325 AutoMutex _l(mLock);
2326 initializeLocked();
2327 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002328
Jeff Brown6328cdc2010-07-29 18:18:33 -07002329 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002330}
2331
2332void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002333 // Preprocess pointer data.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002334 if (mParameters.useBadTouchFilter) {
2335 if (applyBadTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002336 havePointerIds = false;
2337 }
2338 }
2339
Jeff Brown6d0fec22010-07-23 21:28:06 -07002340 if (mParameters.useJumpyTouchFilter) {
2341 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002342 havePointerIds = false;
2343 }
2344 }
2345
2346 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002347 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002348 }
2349
Jeff Brown6d0fec22010-07-23 21:28:06 -07002350 TouchData temp;
2351 TouchData* savedTouch;
2352 if (mParameters.useAveragingTouchFilter) {
2353 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002354 savedTouch = & temp;
2355
Jeff Brown6d0fec22010-07-23 21:28:06 -07002356 applyAveragingTouchFilter();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002357 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002358 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002359 }
2360
Jeff Brown56194eb2011-03-02 19:23:13 -08002361 uint32_t policyFlags = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -08002362 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brown56194eb2011-03-02 19:23:13 -08002363 // Hide the pointer on an initial down.
Jeff Brown05dc66a2011-03-02 14:41:58 -08002364 getContext()->fadePointer();
Jeff Brown56194eb2011-03-02 19:23:13 -08002365
2366 // Initial downs on external touch devices should wake the device.
2367 // We don't do this for internal touch screens to prevent them from waking
2368 // up in your pocket.
2369 // TODO: Use the input device configuration to control this behavior more finely.
2370 if (getDevice()->isExternal()) {
2371 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2372 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002373 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002374
Jeff Brown05dc66a2011-03-02 14:41:58 -08002375 // Process touches and virtual keys.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002376 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2377 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002378 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002379 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002380 }
2381
Jeff Brown6328cdc2010-07-29 18:18:33 -07002382 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002383 if (touchResult == DROP_STROKE) {
2384 mLastTouch.clear();
2385 } else {
2386 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002387 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002388}
2389
Jeff Brown6d0fec22010-07-23 21:28:06 -07002390TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2391 nsecs_t when, uint32_t policyFlags) {
2392 int32_t keyEventAction, keyEventFlags;
2393 int32_t keyCode, scanCode, downTime;
2394 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002395
Jeff Brown6328cdc2010-07-29 18:18:33 -07002396 { // acquire lock
2397 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002398
Jeff Brown6328cdc2010-07-29 18:18:33 -07002399 // Update surface size and orientation, including virtual key positions.
2400 if (! configureSurfaceLocked()) {
2401 return DROP_STROKE;
2402 }
2403
2404 // Check for virtual key press.
2405 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002406 if (mCurrentTouch.pointerCount == 0) {
2407 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002408 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002409#if DEBUG_VIRTUAL_KEYS
2410 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002411 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002412#endif
2413 keyEventAction = AKEY_EVENT_ACTION_UP;
2414 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2415 touchResult = SKIP_TOUCH;
2416 goto DispatchVirtualKey;
2417 }
2418
2419 if (mCurrentTouch.pointerCount == 1) {
2420 int32_t x = mCurrentTouch.pointers[0].x;
2421 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002422 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2423 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002424 // Pointer is still within the space of the virtual key.
2425 return SKIP_TOUCH;
2426 }
2427 }
2428
2429 // Pointer left virtual key area or another pointer also went down.
2430 // Send key cancellation and drop the stroke so subsequent motions will be
2431 // considered fresh downs. This is useful when the user swipes away from the
2432 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002433 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002434#if DEBUG_VIRTUAL_KEYS
2435 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002436 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002437#endif
2438 keyEventAction = AKEY_EVENT_ACTION_UP;
2439 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2440 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002441
2442 // Check whether the pointer moved inside the display area where we should
2443 // start a new stroke.
2444 int32_t x = mCurrentTouch.pointers[0].x;
2445 int32_t y = mCurrentTouch.pointers[0].y;
2446 if (isPointInsideSurfaceLocked(x, y)) {
2447 mLastTouch.clear();
2448 touchResult = DISPATCH_TOUCH;
2449 } else {
2450 touchResult = DROP_STROKE;
2451 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002452 } else {
2453 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2454 // Pointer just went down. Handle off-screen touches, if needed.
2455 int32_t x = mCurrentTouch.pointers[0].x;
2456 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002457 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002458 // If exactly one pointer went down, check for virtual key hit.
2459 // Otherwise we will drop the entire stroke.
2460 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002461 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002462 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002463 if (mContext->shouldDropVirtualKey(when, getDevice(),
2464 virtualKey->keyCode, virtualKey->scanCode)) {
2465 return DROP_STROKE;
2466 }
2467
Jeff Brown6328cdc2010-07-29 18:18:33 -07002468 mLocked.currentVirtualKey.down = true;
2469 mLocked.currentVirtualKey.downTime = when;
2470 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2471 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002472#if DEBUG_VIRTUAL_KEYS
2473 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002474 mLocked.currentVirtualKey.keyCode,
2475 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002476#endif
2477 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2478 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2479 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2480 touchResult = SKIP_TOUCH;
2481 goto DispatchVirtualKey;
2482 }
2483 }
2484 return DROP_STROKE;
2485 }
2486 }
2487 return DISPATCH_TOUCH;
2488 }
2489
2490 DispatchVirtualKey:
2491 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002492 keyCode = mLocked.currentVirtualKey.keyCode;
2493 scanCode = mLocked.currentVirtualKey.scanCode;
2494 downTime = mLocked.currentVirtualKey.downTime;
2495 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002496
2497 // Dispatch virtual key.
2498 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002499 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002500 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2501 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2502 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002503}
2504
Jeff Brownfe508922011-01-18 15:10:10 -08002505void TouchInputMapper::detectGestures(nsecs_t when) {
2506 // Disable all virtual key touches that happen within a short time interval of the
2507 // most recent touch. The idea is to filter out stray virtual key presses when
2508 // interacting with the touch screen.
2509 //
2510 // Problems we're trying to solve:
2511 //
2512 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2513 // virtual key area that is implemented by a separate touch panel and accidentally
2514 // triggers a virtual key.
2515 //
2516 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2517 // area and accidentally triggers a virtual key. This often happens when virtual keys
2518 // are layed out below the screen near to where the on screen keyboard's space bar
2519 // is displayed.
2520 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2521 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2522 }
2523}
2524
Jeff Brown6d0fec22010-07-23 21:28:06 -07002525void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2526 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2527 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002528 if (currentPointerCount == 0 && lastPointerCount == 0) {
2529 return; // nothing to do!
2530 }
2531
Jeff Brown6d0fec22010-07-23 21:28:06 -07002532 BitSet32 currentIdBits = mCurrentTouch.idBits;
2533 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002534
2535 if (currentIdBits == lastIdBits) {
2536 // No pointer id changes so this is a move event.
2537 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002538 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002539 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002540 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002541 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002542 // There may be pointers going up and pointers going down and pointers moving
2543 // all at the same time.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002544 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2545 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2546 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002547 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002548
Jeff Brownc3db8582010-10-20 15:33:38 -07002549 // Produce an intermediate representation of the touch data that consists of the
2550 // old location of pointers that have just gone up and the new location of pointers that
2551 // have just moved but omits the location of pointers that have just gone down.
2552 TouchData interimTouch;
2553 interimTouch.copyFrom(mLastTouch);
2554
2555 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2556 bool moveNeeded = false;
2557 while (!moveIdBits.isEmpty()) {
2558 uint32_t moveId = moveIdBits.firstMarkedBit();
2559 moveIdBits.clearBit(moveId);
2560
2561 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2562 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2563 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2564 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2565 moveNeeded = true;
2566 }
2567 }
2568
2569 // Dispatch pointer up events using the interim pointer locations.
2570 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002571 uint32_t upId = upIdBits.firstMarkedBit();
2572 upIdBits.clearBit(upId);
2573 BitSet32 oldActiveIdBits = activeIdBits;
2574 activeIdBits.clearBit(upId);
2575
2576 int32_t motionEventAction;
2577 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002578 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002579 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002580 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002581 }
2582
Jeff Brownc3db8582010-10-20 15:33:38 -07002583 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002584 oldActiveIdBits, upId, pointerCount, motionEventAction);
2585 pointerCount -= 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002586 }
2587
Jeff Brownc3db8582010-10-20 15:33:38 -07002588 // Dispatch move events if any of the remaining pointers moved from their old locations.
2589 // Although applications receive new locations as part of individual pointer up
2590 // events, they do not generally handle them except when presented in a move event.
2591 if (moveNeeded) {
2592 dispatchTouch(when, policyFlags, &mCurrentTouch,
2593 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2594 }
2595
2596 // Dispatch pointer down events using the new pointer locations.
2597 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002598 uint32_t downId = downIdBits.firstMarkedBit();
2599 downIdBits.clearBit(downId);
2600 BitSet32 oldActiveIdBits = activeIdBits;
2601 activeIdBits.markBit(downId);
2602
2603 int32_t motionEventAction;
2604 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002605 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002606 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002607 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002608 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002609 }
2610
Jeff Brown8d608662010-08-30 03:02:23 -07002611 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002612 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002613 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002614 }
2615 }
2616}
2617
Jeff Brown6d0fec22010-07-23 21:28:06 -07002618void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002619 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002620 int32_t motionEventAction) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002621 int32_t pointerIds[MAX_POINTERS];
2622 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002623 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002624 float xPrecision, yPrecision;
2625
2626 { // acquire lock
2627 AutoMutex _l(mLock);
2628
2629 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2630 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002631 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002632 uint32_t id = idBits.firstMarkedBit();
2633 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002634 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002635
Jeff Brown8d608662010-08-30 03:02:23 -07002636 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002637
Jeff Brown8d608662010-08-30 03:02:23 -07002638 // X and Y
2639 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2640 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002641
Jeff Brown8d608662010-08-30 03:02:23 -07002642 // ToolMajor and ToolMinor
2643 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002644 switch (mCalibration.toolSizeCalibration) {
2645 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002646 toolMajor = in.toolMajor * mLocked.geometricScale;
2647 if (mRawAxes.toolMinor.valid) {
2648 toolMinor = in.toolMinor * mLocked.geometricScale;
2649 } else {
2650 toolMinor = toolMajor;
2651 }
2652 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002653 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002654 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002655 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002656 : 0;
2657 if (mRawAxes.toolMinor.valid) {
2658 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002659 ? in.toolMinor * mLocked.toolSizeLinearScale
2660 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002661 : 0;
2662 } else {
2663 toolMinor = toolMajor;
2664 }
2665 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002666 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2667 if (in.toolMajor != 0) {
2668 float diameter = sqrtf(in.toolMajor
2669 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2670 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2671 } else {
2672 toolMajor = 0;
2673 }
2674 toolMinor = toolMajor;
2675 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002676 default:
2677 toolMajor = 0;
2678 toolMinor = 0;
2679 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002680 }
2681
Jeff Brownc6d282b2010-10-14 21:42:15 -07002682 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002683 toolMajor /= pointerCount;
2684 toolMinor /= pointerCount;
2685 }
2686
2687 // Pressure
2688 float rawPressure;
2689 switch (mCalibration.pressureSource) {
2690 case Calibration::PRESSURE_SOURCE_PRESSURE:
2691 rawPressure = in.pressure;
2692 break;
2693 case Calibration::PRESSURE_SOURCE_TOUCH:
2694 rawPressure = in.touchMajor;
2695 break;
2696 default:
2697 rawPressure = 0;
2698 }
2699
2700 float pressure;
2701 switch (mCalibration.pressureCalibration) {
2702 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2703 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2704 pressure = rawPressure * mLocked.pressureScale;
2705 break;
2706 default:
2707 pressure = 1;
2708 break;
2709 }
2710
2711 // TouchMajor and TouchMinor
2712 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002713 switch (mCalibration.touchSizeCalibration) {
2714 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002715 touchMajor = in.touchMajor * mLocked.geometricScale;
2716 if (mRawAxes.touchMinor.valid) {
2717 touchMinor = in.touchMinor * mLocked.geometricScale;
2718 } else {
2719 touchMinor = touchMajor;
2720 }
2721 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002722 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002723 touchMajor = toolMajor * pressure;
2724 touchMinor = toolMinor * pressure;
2725 break;
2726 default:
2727 touchMajor = 0;
2728 touchMinor = 0;
2729 break;
2730 }
2731
2732 if (touchMajor > toolMajor) {
2733 touchMajor = toolMajor;
2734 }
2735 if (touchMinor > toolMinor) {
2736 touchMinor = toolMinor;
2737 }
2738
2739 // Size
2740 float size;
2741 switch (mCalibration.sizeCalibration) {
2742 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2743 float rawSize = mRawAxes.toolMinor.valid
2744 ? avg(in.toolMajor, in.toolMinor)
2745 : in.toolMajor;
2746 size = rawSize * mLocked.sizeScale;
2747 break;
2748 }
2749 default:
2750 size = 0;
2751 break;
2752 }
2753
2754 // Orientation
2755 float orientation;
2756 switch (mCalibration.orientationCalibration) {
2757 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2758 orientation = in.orientation * mLocked.orientationScale;
2759 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002760 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2761 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2762 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2763 if (c1 != 0 || c2 != 0) {
2764 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002765 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2766 touchMajor *= scale;
2767 touchMinor /= scale;
2768 toolMajor *= scale;
2769 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002770 } else {
2771 orientation = 0;
2772 }
2773 break;
2774 }
Jeff Brown8d608662010-08-30 03:02:23 -07002775 default:
2776 orientation = 0;
2777 }
2778
2779 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002780 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002781 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002782 float xTemp = x;
2783 x = y;
2784 y = mLocked.surfaceWidth - xTemp;
2785 orientation -= M_PI_2;
2786 if (orientation < - M_PI_2) {
2787 orientation += M_PI;
2788 }
2789 break;
2790 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002791 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002792 x = mLocked.surfaceWidth - x;
2793 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002794 break;
2795 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002796 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002797 float xTemp = x;
2798 x = mLocked.surfaceHeight - y;
2799 y = xTemp;
2800 orientation += M_PI_2;
2801 if (orientation > M_PI_2) {
2802 orientation -= M_PI;
2803 }
2804 break;
2805 }
2806 }
2807
Jeff Brown8d608662010-08-30 03:02:23 -07002808 // Write output coords.
2809 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002810 out.clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -08002811 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2812 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2813 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2814 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2815 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2816 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2817 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2818 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2819 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002820
Jeff Brown8d608662010-08-30 03:02:23 -07002821 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002822
2823 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002824 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002825 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002826 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002827
2828 // Check edge flags by looking only at the first pointer since the flags are
2829 // global to the event.
2830 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownebbd5d12011-02-17 13:01:34 -08002831 float x = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
2832 float y = pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08002833
2834 if (x <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002835 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002836 } else if (x >= mLocked.orientedSurfaceWidth) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002837 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2838 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08002839 if (y <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002840 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002841 } else if (y >= mLocked.orientedSurfaceHeight) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002842 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2843 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002844 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002845
2846 xPrecision = mLocked.orientedXPrecision;
2847 yPrecision = mLocked.orientedYPrecision;
2848 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002849
Jeff Brown83c09682010-12-23 17:50:18 -08002850 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002851 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002852 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002853 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002854}
2855
Jeff Brown6328cdc2010-07-29 18:18:33 -07002856bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002857 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2858 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2859 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002860 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002861 return true;
2862}
2863
Jeff Brown6328cdc2010-07-29 18:18:33 -07002864const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2865 int32_t x, int32_t y) {
2866 size_t numVirtualKeys = mLocked.virtualKeys.size();
2867 for (size_t i = 0; i < numVirtualKeys; i++) {
2868 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002869
2870#if DEBUG_VIRTUAL_KEYS
2871 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2872 "left=%d, top=%d, right=%d, bottom=%d",
2873 x, y,
2874 virtualKey.keyCode, virtualKey.scanCode,
2875 virtualKey.hitLeft, virtualKey.hitTop,
2876 virtualKey.hitRight, virtualKey.hitBottom);
2877#endif
2878
2879 if (virtualKey.isHit(x, y)) {
2880 return & virtualKey;
2881 }
2882 }
2883
2884 return NULL;
2885}
2886
2887void TouchInputMapper::calculatePointerIds() {
2888 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2889 uint32_t lastPointerCount = mLastTouch.pointerCount;
2890
2891 if (currentPointerCount == 0) {
2892 // No pointers to assign.
2893 mCurrentTouch.idBits.clear();
2894 } else if (lastPointerCount == 0) {
2895 // All pointers are new.
2896 mCurrentTouch.idBits.clear();
2897 for (uint32_t i = 0; i < currentPointerCount; i++) {
2898 mCurrentTouch.pointers[i].id = i;
2899 mCurrentTouch.idToIndex[i] = i;
2900 mCurrentTouch.idBits.markBit(i);
2901 }
2902 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2903 // Only one pointer and no change in count so it must have the same id as before.
2904 uint32_t id = mLastTouch.pointers[0].id;
2905 mCurrentTouch.pointers[0].id = id;
2906 mCurrentTouch.idToIndex[id] = 0;
2907 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2908 } else {
2909 // General case.
2910 // We build a heap of squared euclidean distances between current and last pointers
2911 // associated with the current and last pointer indices. Then, we find the best
2912 // match (by distance) for each current pointer.
2913 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2914
2915 uint32_t heapSize = 0;
2916 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2917 currentPointerIndex++) {
2918 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2919 lastPointerIndex++) {
2920 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2921 - mLastTouch.pointers[lastPointerIndex].x;
2922 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2923 - mLastTouch.pointers[lastPointerIndex].y;
2924
2925 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2926
2927 // Insert new element into the heap (sift up).
2928 heap[heapSize].currentPointerIndex = currentPointerIndex;
2929 heap[heapSize].lastPointerIndex = lastPointerIndex;
2930 heap[heapSize].distance = distance;
2931 heapSize += 1;
2932 }
2933 }
2934
2935 // Heapify
2936 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2937 startIndex -= 1;
2938 for (uint32_t parentIndex = startIndex; ;) {
2939 uint32_t childIndex = parentIndex * 2 + 1;
2940 if (childIndex >= heapSize) {
2941 break;
2942 }
2943
2944 if (childIndex + 1 < heapSize
2945 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2946 childIndex += 1;
2947 }
2948
2949 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2950 break;
2951 }
2952
2953 swap(heap[parentIndex], heap[childIndex]);
2954 parentIndex = childIndex;
2955 }
2956 }
2957
2958#if DEBUG_POINTER_ASSIGNMENT
2959 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2960 for (size_t i = 0; i < heapSize; i++) {
2961 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2962 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2963 heap[i].distance);
2964 }
2965#endif
2966
2967 // Pull matches out by increasing order of distance.
2968 // To avoid reassigning pointers that have already been matched, the loop keeps track
2969 // of which last and current pointers have been matched using the matchedXXXBits variables.
2970 // It also tracks the used pointer id bits.
2971 BitSet32 matchedLastBits(0);
2972 BitSet32 matchedCurrentBits(0);
2973 BitSet32 usedIdBits(0);
2974 bool first = true;
2975 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2976 for (;;) {
2977 if (first) {
2978 // The first time through the loop, we just consume the root element of
2979 // the heap (the one with smallest distance).
2980 first = false;
2981 } else {
2982 // Previous iterations consumed the root element of the heap.
2983 // Pop root element off of the heap (sift down).
2984 heapSize -= 1;
2985 assert(heapSize > 0);
2986
2987 // Sift down.
2988 heap[0] = heap[heapSize];
2989 for (uint32_t parentIndex = 0; ;) {
2990 uint32_t childIndex = parentIndex * 2 + 1;
2991 if (childIndex >= heapSize) {
2992 break;
2993 }
2994
2995 if (childIndex + 1 < heapSize
2996 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2997 childIndex += 1;
2998 }
2999
3000 if (heap[parentIndex].distance <= heap[childIndex].distance) {
3001 break;
3002 }
3003
3004 swap(heap[parentIndex], heap[childIndex]);
3005 parentIndex = childIndex;
3006 }
3007
3008#if DEBUG_POINTER_ASSIGNMENT
3009 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
3010 for (size_t i = 0; i < heapSize; i++) {
3011 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
3012 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
3013 heap[i].distance);
3014 }
3015#endif
3016 }
3017
3018 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
3019 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
3020
3021 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
3022 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
3023
3024 matchedCurrentBits.markBit(currentPointerIndex);
3025 matchedLastBits.markBit(lastPointerIndex);
3026
3027 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
3028 mCurrentTouch.pointers[currentPointerIndex].id = id;
3029 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3030 usedIdBits.markBit(id);
3031
3032#if DEBUG_POINTER_ASSIGNMENT
3033 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
3034 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
3035#endif
3036 break;
3037 }
3038 }
3039
3040 // Assign fresh ids to new pointers.
3041 if (currentPointerCount > lastPointerCount) {
3042 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
3043 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
3044 uint32_t id = usedIdBits.firstUnmarkedBit();
3045
3046 mCurrentTouch.pointers[currentPointerIndex].id = id;
3047 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3048 usedIdBits.markBit(id);
3049
3050#if DEBUG_POINTER_ASSIGNMENT
3051 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
3052 currentPointerIndex, id);
3053#endif
3054
3055 if (--i == 0) break; // done
3056 matchedCurrentBits.markBit(currentPointerIndex);
3057 }
3058 }
3059
3060 // Fix id bits.
3061 mCurrentTouch.idBits = usedIdBits;
3062 }
3063}
3064
3065/* Special hack for devices that have bad screen data: if one of the
3066 * points has moved more than a screen height from the last position,
3067 * then drop it. */
3068bool TouchInputMapper::applyBadTouchFilter() {
3069 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003070 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003071 return false;
3072 }
3073
3074 uint32_t pointerCount = mCurrentTouch.pointerCount;
3075
3076 // Nothing to do if there are no points.
3077 if (pointerCount == 0) {
3078 return false;
3079 }
3080
3081 // Don't do anything if a finger is going down or up. We run
3082 // here before assigning pointer IDs, so there isn't a good
3083 // way to do per-finger matching.
3084 if (pointerCount != mLastTouch.pointerCount) {
3085 return false;
3086 }
3087
3088 // We consider a single movement across more than a 7/16 of
3089 // the long size of the screen to be bad. This was a magic value
3090 // determined by looking at the maximum distance it is feasible
3091 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07003092 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003093
3094 // XXX The original code in InputDevice.java included commented out
3095 // code for testing the X axis. Note that when we drop a point
3096 // we don't actually restore the old X either. Strange.
3097 // The old code also tries to track when bad points were previously
3098 // detected but it turns out that due to the placement of a "break"
3099 // at the end of the loop, we never set mDroppedBadPoint to true
3100 // so it is effectively dead code.
3101 // Need to figure out if the old code is busted or just overcomplicated
3102 // but working as intended.
3103
3104 // Look through all new points and see if any are farther than
3105 // acceptable from all previous points.
3106 for (uint32_t i = pointerCount; i-- > 0; ) {
3107 int32_t y = mCurrentTouch.pointers[i].y;
3108 int32_t closestY = INT_MAX;
3109 int32_t closestDeltaY = 0;
3110
3111#if DEBUG_HACKS
3112 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3113#endif
3114
3115 for (uint32_t j = pointerCount; j-- > 0; ) {
3116 int32_t lastY = mLastTouch.pointers[j].y;
3117 int32_t deltaY = abs(y - lastY);
3118
3119#if DEBUG_HACKS
3120 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3121 j, lastY, deltaY);
3122#endif
3123
3124 if (deltaY < maxDeltaY) {
3125 goto SkipSufficientlyClosePoint;
3126 }
3127 if (deltaY < closestDeltaY) {
3128 closestDeltaY = deltaY;
3129 closestY = lastY;
3130 }
3131 }
3132
3133 // Must not have found a close enough match.
3134#if DEBUG_HACKS
3135 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3136 i, y, closestY, closestDeltaY, maxDeltaY);
3137#endif
3138
3139 mCurrentTouch.pointers[i].y = closestY;
3140 return true; // XXX original code only corrects one point
3141
3142 SkipSufficientlyClosePoint: ;
3143 }
3144
3145 // No change.
3146 return false;
3147}
3148
3149/* Special hack for devices that have bad screen data: drop points where
3150 * the coordinate value for one axis has jumped to the other pointer's location.
3151 */
3152bool TouchInputMapper::applyJumpyTouchFilter() {
3153 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003154 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003155 return false;
3156 }
3157
3158 uint32_t pointerCount = mCurrentTouch.pointerCount;
3159 if (mLastTouch.pointerCount != pointerCount) {
3160#if DEBUG_HACKS
3161 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3162 mLastTouch.pointerCount, pointerCount);
3163 for (uint32_t i = 0; i < pointerCount; i++) {
3164 LOGD(" Pointer %d (%d, %d)", i,
3165 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3166 }
3167#endif
3168
3169 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3170 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3171 // Just drop the first few events going from 1 to 2 pointers.
3172 // They're bad often enough that they're not worth considering.
3173 mCurrentTouch.pointerCount = 1;
3174 mJumpyTouchFilter.jumpyPointsDropped += 1;
3175
3176#if DEBUG_HACKS
3177 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3178#endif
3179 return true;
3180 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3181 // The event when we go from 2 -> 1 tends to be messed up too
3182 mCurrentTouch.pointerCount = 2;
3183 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3184 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3185 mJumpyTouchFilter.jumpyPointsDropped += 1;
3186
3187#if DEBUG_HACKS
3188 for (int32_t i = 0; i < 2; i++) {
3189 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3190 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3191 }
3192#endif
3193 return true;
3194 }
3195 }
3196 // Reset jumpy points dropped on other transitions or if limit exceeded.
3197 mJumpyTouchFilter.jumpyPointsDropped = 0;
3198
3199#if DEBUG_HACKS
3200 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3201#endif
3202 return false;
3203 }
3204
3205 // We have the same number of pointers as last time.
3206 // A 'jumpy' point is one where the coordinate value for one axis
3207 // has jumped to the other pointer's location. No need to do anything
3208 // else if we only have one pointer.
3209 if (pointerCount < 2) {
3210 return false;
3211 }
3212
3213 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003214 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003215
3216 // We only replace the single worst jumpy point as characterized by pointer distance
3217 // in a single axis.
3218 int32_t badPointerIndex = -1;
3219 int32_t badPointerReplacementIndex = -1;
3220 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3221
3222 for (uint32_t i = pointerCount; i-- > 0; ) {
3223 int32_t x = mCurrentTouch.pointers[i].x;
3224 int32_t y = mCurrentTouch.pointers[i].y;
3225
3226#if DEBUG_HACKS
3227 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3228#endif
3229
3230 // Check if a touch point is too close to another's coordinates
3231 bool dropX = false, dropY = false;
3232 for (uint32_t j = 0; j < pointerCount; j++) {
3233 if (i == j) {
3234 continue;
3235 }
3236
3237 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3238 dropX = true;
3239 break;
3240 }
3241
3242 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3243 dropY = true;
3244 break;
3245 }
3246 }
3247 if (! dropX && ! dropY) {
3248 continue; // not jumpy
3249 }
3250
3251 // Find a replacement candidate by comparing with older points on the
3252 // complementary (non-jumpy) axis.
3253 int32_t distance = INT_MIN; // distance to be corrected
3254 int32_t replacementIndex = -1;
3255
3256 if (dropX) {
3257 // X looks too close. Find an older replacement point with a close Y.
3258 int32_t smallestDeltaY = INT_MAX;
3259 for (uint32_t j = 0; j < pointerCount; j++) {
3260 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3261 if (deltaY < smallestDeltaY) {
3262 smallestDeltaY = deltaY;
3263 replacementIndex = j;
3264 }
3265 }
3266 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3267 } else {
3268 // Y looks too close. Find an older replacement point with a close X.
3269 int32_t smallestDeltaX = INT_MAX;
3270 for (uint32_t j = 0; j < pointerCount; j++) {
3271 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3272 if (deltaX < smallestDeltaX) {
3273 smallestDeltaX = deltaX;
3274 replacementIndex = j;
3275 }
3276 }
3277 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3278 }
3279
3280 // If replacing this pointer would correct a worse error than the previous ones
3281 // considered, then use this replacement instead.
3282 if (distance > badPointerDistance) {
3283 badPointerIndex = i;
3284 badPointerReplacementIndex = replacementIndex;
3285 badPointerDistance = distance;
3286 }
3287 }
3288
3289 // Correct the jumpy pointer if one was found.
3290 if (badPointerIndex >= 0) {
3291#if DEBUG_HACKS
3292 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3293 badPointerIndex,
3294 mLastTouch.pointers[badPointerReplacementIndex].x,
3295 mLastTouch.pointers[badPointerReplacementIndex].y);
3296#endif
3297
3298 mCurrentTouch.pointers[badPointerIndex].x =
3299 mLastTouch.pointers[badPointerReplacementIndex].x;
3300 mCurrentTouch.pointers[badPointerIndex].y =
3301 mLastTouch.pointers[badPointerReplacementIndex].y;
3302 mJumpyTouchFilter.jumpyPointsDropped += 1;
3303 return true;
3304 }
3305 }
3306
3307 mJumpyTouchFilter.jumpyPointsDropped = 0;
3308 return false;
3309}
3310
3311/* Special hack for devices that have bad screen data: aggregate and
3312 * compute averages of the coordinate data, to reduce the amount of
3313 * jitter seen by applications. */
3314void TouchInputMapper::applyAveragingTouchFilter() {
3315 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3316 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3317 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3318 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003319 int32_t pressure;
3320 switch (mCalibration.pressureSource) {
3321 case Calibration::PRESSURE_SOURCE_PRESSURE:
3322 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3323 break;
3324 case Calibration::PRESSURE_SOURCE_TOUCH:
3325 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3326 break;
3327 default:
3328 pressure = 1;
3329 break;
3330 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003331
3332 if (mLastTouch.idBits.hasBit(id)) {
3333 // Pointer was down before and is still down now.
3334 // Compute average over history trace.
3335 uint32_t start = mAveragingTouchFilter.historyStart[id];
3336 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3337
3338 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3339 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3340 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3341
3342#if DEBUG_HACKS
3343 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3344 id, distance);
3345#endif
3346
3347 if (distance < AVERAGING_DISTANCE_LIMIT) {
3348 // Increment end index in preparation for recording new historical data.
3349 end += 1;
3350 if (end > AVERAGING_HISTORY_SIZE) {
3351 end = 0;
3352 }
3353
3354 // If the end index has looped back to the start index then we have filled
3355 // the historical trace up to the desired size so we drop the historical
3356 // data at the start of the trace.
3357 if (end == start) {
3358 start += 1;
3359 if (start > AVERAGING_HISTORY_SIZE) {
3360 start = 0;
3361 }
3362 }
3363
3364 // Add the raw data to the historical trace.
3365 mAveragingTouchFilter.historyStart[id] = start;
3366 mAveragingTouchFilter.historyEnd[id] = end;
3367 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3368 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3369 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3370
3371 // Average over all historical positions in the trace by total pressure.
3372 int32_t averagedX = 0;
3373 int32_t averagedY = 0;
3374 int32_t totalPressure = 0;
3375 for (;;) {
3376 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3377 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3378 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3379 .pointers[id].pressure;
3380
3381 averagedX += historicalX * historicalPressure;
3382 averagedY += historicalY * historicalPressure;
3383 totalPressure += historicalPressure;
3384
3385 if (start == end) {
3386 break;
3387 }
3388
3389 start += 1;
3390 if (start > AVERAGING_HISTORY_SIZE) {
3391 start = 0;
3392 }
3393 }
3394
Jeff Brown8d608662010-08-30 03:02:23 -07003395 if (totalPressure != 0) {
3396 averagedX /= totalPressure;
3397 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003398
3399#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003400 LOGD("AveragingTouchFilter: Pointer id %d - "
3401 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3402 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003403#endif
3404
Jeff Brown8d608662010-08-30 03:02:23 -07003405 mCurrentTouch.pointers[currentIndex].x = averagedX;
3406 mCurrentTouch.pointers[currentIndex].y = averagedY;
3407 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003408 } else {
3409#if DEBUG_HACKS
3410 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3411#endif
3412 }
3413 } else {
3414#if DEBUG_HACKS
3415 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3416#endif
3417 }
3418
3419 // Reset pointer history.
3420 mAveragingTouchFilter.historyStart[id] = 0;
3421 mAveragingTouchFilter.historyEnd[id] = 0;
3422 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3423 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3424 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3425 }
3426}
3427
3428int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003429 { // acquire lock
3430 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003431
Jeff Brown6328cdc2010-07-29 18:18:33 -07003432 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003433 return AKEY_STATE_VIRTUAL;
3434 }
3435
Jeff Brown6328cdc2010-07-29 18:18:33 -07003436 size_t numVirtualKeys = mLocked.virtualKeys.size();
3437 for (size_t i = 0; i < numVirtualKeys; i++) {
3438 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003439 if (virtualKey.keyCode == keyCode) {
3440 return AKEY_STATE_UP;
3441 }
3442 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003443 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003444
3445 return AKEY_STATE_UNKNOWN;
3446}
3447
3448int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003449 { // acquire lock
3450 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003451
Jeff Brown6328cdc2010-07-29 18:18:33 -07003452 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003453 return AKEY_STATE_VIRTUAL;
3454 }
3455
Jeff Brown6328cdc2010-07-29 18:18:33 -07003456 size_t numVirtualKeys = mLocked.virtualKeys.size();
3457 for (size_t i = 0; i < numVirtualKeys; i++) {
3458 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003459 if (virtualKey.scanCode == scanCode) {
3460 return AKEY_STATE_UP;
3461 }
3462 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003463 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003464
3465 return AKEY_STATE_UNKNOWN;
3466}
3467
3468bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3469 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003470 { // acquire lock
3471 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003472
Jeff Brown6328cdc2010-07-29 18:18:33 -07003473 size_t numVirtualKeys = mLocked.virtualKeys.size();
3474 for (size_t i = 0; i < numVirtualKeys; i++) {
3475 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003476
3477 for (size_t i = 0; i < numCodes; i++) {
3478 if (virtualKey.keyCode == keyCodes[i]) {
3479 outFlags[i] = 1;
3480 }
3481 }
3482 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003483 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003484
3485 return true;
3486}
3487
3488
3489// --- SingleTouchInputMapper ---
3490
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003491SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3492 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003493 initialize();
3494}
3495
3496SingleTouchInputMapper::~SingleTouchInputMapper() {
3497}
3498
3499void SingleTouchInputMapper::initialize() {
3500 mAccumulator.clear();
3501
3502 mDown = false;
3503 mX = 0;
3504 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003505 mPressure = 0; // default to 0 for devices that don't report pressure
3506 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003507}
3508
3509void SingleTouchInputMapper::reset() {
3510 TouchInputMapper::reset();
3511
Jeff Brown6d0fec22010-07-23 21:28:06 -07003512 initialize();
3513 }
3514
3515void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3516 switch (rawEvent->type) {
3517 case EV_KEY:
3518 switch (rawEvent->scanCode) {
3519 case BTN_TOUCH:
3520 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3521 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003522 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3523 // not have received valid position information yet. This logic assumes that
3524 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003525 break;
3526 }
3527 break;
3528
3529 case EV_ABS:
3530 switch (rawEvent->scanCode) {
3531 case ABS_X:
3532 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3533 mAccumulator.absX = rawEvent->value;
3534 break;
3535 case ABS_Y:
3536 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3537 mAccumulator.absY = rawEvent->value;
3538 break;
3539 case ABS_PRESSURE:
3540 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3541 mAccumulator.absPressure = rawEvent->value;
3542 break;
3543 case ABS_TOOL_WIDTH:
3544 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3545 mAccumulator.absToolWidth = rawEvent->value;
3546 break;
3547 }
3548 break;
3549
3550 case EV_SYN:
3551 switch (rawEvent->scanCode) {
3552 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003553 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003554 break;
3555 }
3556 break;
3557 }
3558}
3559
3560void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003561 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003562 if (fields == 0) {
3563 return; // no new state changes, so nothing to do
3564 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003565
3566 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3567 mDown = mAccumulator.btnTouch;
3568 }
3569
3570 if (fields & Accumulator::FIELD_ABS_X) {
3571 mX = mAccumulator.absX;
3572 }
3573
3574 if (fields & Accumulator::FIELD_ABS_Y) {
3575 mY = mAccumulator.absY;
3576 }
3577
3578 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3579 mPressure = mAccumulator.absPressure;
3580 }
3581
3582 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003583 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003584 }
3585
3586 mCurrentTouch.clear();
3587
3588 if (mDown) {
3589 mCurrentTouch.pointerCount = 1;
3590 mCurrentTouch.pointers[0].id = 0;
3591 mCurrentTouch.pointers[0].x = mX;
3592 mCurrentTouch.pointers[0].y = mY;
3593 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003594 mCurrentTouch.pointers[0].touchMajor = 0;
3595 mCurrentTouch.pointers[0].touchMinor = 0;
3596 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3597 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003598 mCurrentTouch.pointers[0].orientation = 0;
3599 mCurrentTouch.idToIndex[0] = 0;
3600 mCurrentTouch.idBits.markBit(0);
3601 }
3602
3603 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003604
3605 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003606}
3607
Jeff Brown8d608662010-08-30 03:02:23 -07003608void SingleTouchInputMapper::configureRawAxes() {
3609 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003610
Jeff Brown8d608662010-08-30 03:02:23 -07003611 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3612 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3613 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3614 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003615}
3616
3617
3618// --- MultiTouchInputMapper ---
3619
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003620MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3621 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003622 initialize();
3623}
3624
3625MultiTouchInputMapper::~MultiTouchInputMapper() {
3626}
3627
3628void MultiTouchInputMapper::initialize() {
3629 mAccumulator.clear();
3630}
3631
3632void MultiTouchInputMapper::reset() {
3633 TouchInputMapper::reset();
3634
Jeff Brown6d0fec22010-07-23 21:28:06 -07003635 initialize();
3636}
3637
3638void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3639 switch (rawEvent->type) {
3640 case EV_ABS: {
3641 uint32_t pointerIndex = mAccumulator.pointerCount;
3642 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3643
3644 switch (rawEvent->scanCode) {
3645 case ABS_MT_POSITION_X:
3646 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3647 pointer->absMTPositionX = rawEvent->value;
3648 break;
3649 case ABS_MT_POSITION_Y:
3650 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3651 pointer->absMTPositionY = rawEvent->value;
3652 break;
3653 case ABS_MT_TOUCH_MAJOR:
3654 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3655 pointer->absMTTouchMajor = rawEvent->value;
3656 break;
3657 case ABS_MT_TOUCH_MINOR:
3658 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3659 pointer->absMTTouchMinor = rawEvent->value;
3660 break;
3661 case ABS_MT_WIDTH_MAJOR:
3662 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3663 pointer->absMTWidthMajor = rawEvent->value;
3664 break;
3665 case ABS_MT_WIDTH_MINOR:
3666 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3667 pointer->absMTWidthMinor = rawEvent->value;
3668 break;
3669 case ABS_MT_ORIENTATION:
3670 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3671 pointer->absMTOrientation = rawEvent->value;
3672 break;
3673 case ABS_MT_TRACKING_ID:
3674 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3675 pointer->absMTTrackingId = rawEvent->value;
3676 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003677 case ABS_MT_PRESSURE:
3678 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3679 pointer->absMTPressure = rawEvent->value;
3680 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003681 }
3682 break;
3683 }
3684
3685 case EV_SYN:
3686 switch (rawEvent->scanCode) {
3687 case SYN_MT_REPORT: {
3688 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3689 uint32_t pointerIndex = mAccumulator.pointerCount;
3690
3691 if (mAccumulator.pointers[pointerIndex].fields) {
3692 if (pointerIndex == MAX_POINTERS) {
3693 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3694 MAX_POINTERS);
3695 } else {
3696 pointerIndex += 1;
3697 mAccumulator.pointerCount = pointerIndex;
3698 }
3699 }
3700
3701 mAccumulator.pointers[pointerIndex].clear();
3702 break;
3703 }
3704
3705 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003706 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003707 break;
3708 }
3709 break;
3710 }
3711}
3712
3713void MultiTouchInputMapper::sync(nsecs_t when) {
3714 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003715 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003716
Jeff Brown6d0fec22010-07-23 21:28:06 -07003717 uint32_t inCount = mAccumulator.pointerCount;
3718 uint32_t outCount = 0;
3719 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003720
Jeff Brown6d0fec22010-07-23 21:28:06 -07003721 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003722
Jeff Brown6d0fec22010-07-23 21:28:06 -07003723 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003724 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3725 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003726
Jeff Brown6d0fec22010-07-23 21:28:06 -07003727 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003728 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3729 // Drop this finger.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003730 continue;
3731 }
3732
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003733 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3734 outPointer.x = inPointer.absMTPositionX;
3735 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003736
Jeff Brown8d608662010-08-30 03:02:23 -07003737 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3738 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003739 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3740 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003741 continue;
3742 }
Jeff Brown8d608662010-08-30 03:02:23 -07003743 outPointer.pressure = inPointer.absMTPressure;
3744 } else {
3745 // Default pressure to 0 if absent.
3746 outPointer.pressure = 0;
3747 }
3748
3749 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3750 if (inPointer.absMTTouchMajor <= 0) {
3751 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3752 // a pointer going up. Drop this finger.
3753 continue;
3754 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003755 outPointer.touchMajor = inPointer.absMTTouchMajor;
3756 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003757 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003758 outPointer.touchMajor = 0;
3759 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003760
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003761 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3762 outPointer.touchMinor = inPointer.absMTTouchMinor;
3763 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003764 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003765 outPointer.touchMinor = outPointer.touchMajor;
3766 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003767
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003768 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3769 outPointer.toolMajor = inPointer.absMTWidthMajor;
3770 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003771 // Default tool area to 0 if absent.
3772 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003773 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003774
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003775 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3776 outPointer.toolMinor = inPointer.absMTWidthMinor;
3777 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003778 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003779 outPointer.toolMinor = outPointer.toolMajor;
3780 }
3781
3782 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3783 outPointer.orientation = inPointer.absMTOrientation;
3784 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003785 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003786 outPointer.orientation = 0;
3787 }
3788
Jeff Brown8d608662010-08-30 03:02:23 -07003789 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003790 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003791 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3792 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003793
Jeff Brown6d0fec22010-07-23 21:28:06 -07003794 if (id > MAX_POINTER_ID) {
3795#if DEBUG_POINTERS
3796 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003797 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003798 id, MAX_POINTER_ID);
3799#endif
3800 havePointerIds = false;
3801 }
3802 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003803 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003804 mCurrentTouch.idToIndex[id] = outCount;
3805 mCurrentTouch.idBits.markBit(id);
3806 }
3807 } else {
3808 havePointerIds = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003809 }
3810 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003811
Jeff Brown6d0fec22010-07-23 21:28:06 -07003812 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003813 }
3814
Jeff Brown6d0fec22010-07-23 21:28:06 -07003815 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003816
Jeff Brown6d0fec22010-07-23 21:28:06 -07003817 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003818
3819 mAccumulator.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003820}
3821
Jeff Brown8d608662010-08-30 03:02:23 -07003822void MultiTouchInputMapper::configureRawAxes() {
3823 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003824
Jeff Brown8d608662010-08-30 03:02:23 -07003825 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3826 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3827 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3828 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3829 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3830 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3831 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3832 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003833}
3834
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003835
Jeff Browncb1404e2011-01-15 18:14:15 -08003836// --- JoystickInputMapper ---
3837
3838JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3839 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08003840}
3841
3842JoystickInputMapper::~JoystickInputMapper() {
3843}
3844
3845uint32_t JoystickInputMapper::getSources() {
3846 return AINPUT_SOURCE_JOYSTICK;
3847}
3848
3849void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3850 InputMapper::populateDeviceInfo(info);
3851
Jeff Brown6f2fba42011-02-19 01:08:02 -08003852 for (size_t i = 0; i < mAxes.size(); i++) {
3853 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08003854 info->addMotionRange(axis.axisInfo.axis, axis.min, axis.max, axis.flat, axis.fuzz);
3855 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
3856 info->addMotionRange(axis.axisInfo.highAxis, axis.min, axis.max, axis.flat, axis.fuzz);
3857 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003858 }
3859}
3860
3861void JoystickInputMapper::dump(String8& dump) {
3862 dump.append(INDENT2 "Joystick Input Mapper:\n");
3863
Jeff Brown6f2fba42011-02-19 01:08:02 -08003864 dump.append(INDENT3 "Axes:\n");
3865 size_t numAxes = mAxes.size();
3866 for (size_t i = 0; i < numAxes; i++) {
3867 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08003868 const char* label = getAxisLabel(axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003869 if (label) {
Jeff Brown85297452011-03-04 13:07:49 -08003870 dump.appendFormat(INDENT4 "%s", label);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003871 } else {
Jeff Brown85297452011-03-04 13:07:49 -08003872 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003873 }
Jeff Brown85297452011-03-04 13:07:49 -08003874 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
3875 label = getAxisLabel(axis.axisInfo.highAxis);
3876 if (label) {
3877 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
3878 } else {
3879 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
3880 axis.axisInfo.splitValue);
3881 }
3882 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
3883 dump.append(" (invert)");
3884 }
3885
3886 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
3887 axis.min, axis.max, axis.flat, axis.fuzz);
3888 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
3889 "highScale=%0.5f, highOffset=%0.5f\n",
3890 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003891 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3892 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3893 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003894 }
3895}
3896
3897void JoystickInputMapper::configure() {
3898 InputMapper::configure();
3899
Jeff Brown6f2fba42011-02-19 01:08:02 -08003900 // Collect all axes.
3901 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3902 RawAbsoluteAxisInfo rawAxisInfo;
3903 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3904 if (rawAxisInfo.valid) {
Jeff Brown85297452011-03-04 13:07:49 -08003905 // Map axis.
3906 AxisInfo axisInfo;
3907 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003908 if (!explicitlyMapped) {
3909 // Axis is not explicitly mapped, will choose a generic axis later.
Jeff Brown85297452011-03-04 13:07:49 -08003910 axisInfo.mode = AxisInfo::MODE_NORMAL;
3911 axisInfo.axis = -1;
Jeff Brown6f2fba42011-02-19 01:08:02 -08003912 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003913
Jeff Brown85297452011-03-04 13:07:49 -08003914 // Apply flat override.
3915 int32_t rawFlat = axisInfo.flatOverride < 0
3916 ? rawAxisInfo.flat : axisInfo.flatOverride;
3917
3918 // Calculate scaling factors and limits.
Jeff Brown6f2fba42011-02-19 01:08:02 -08003919 Axis axis;
Jeff Brown85297452011-03-04 13:07:49 -08003920 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
3921 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
3922 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
3923 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
3924 scale, 0.0f, highScale, 0.0f,
3925 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
3926 } else if (isCenteredAxis(axisInfo.axis)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003927 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3928 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
Jeff Brown85297452011-03-04 13:07:49 -08003929 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
3930 scale, offset, scale, offset,
3931 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003932 } else {
3933 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
Jeff Brown85297452011-03-04 13:07:49 -08003934 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
3935 scale, 0.0f, scale, 0.0f,
3936 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003937 }
3938
3939 // To eliminate noise while the joystick is at rest, filter out small variations
3940 // in axis values up front.
3941 axis.filter = axis.flat * 0.25f;
3942
3943 mAxes.add(abs, axis);
3944 }
3945 }
3946
3947 // If there are too many axes, start dropping them.
3948 // Prefer to keep explicitly mapped axes.
3949 if (mAxes.size() > PointerCoords::MAX_AXES) {
3950 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3951 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3952 pruneAxes(true);
3953 pruneAxes(false);
3954 }
3955
3956 // Assign generic axis ids to remaining axes.
3957 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3958 size_t numAxes = mAxes.size();
3959 for (size_t i = 0; i < numAxes; i++) {
3960 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08003961 if (axis.axisInfo.axis < 0) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003962 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3963 && haveAxis(nextGenericAxisId)) {
3964 nextGenericAxisId += 1;
3965 }
3966
3967 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
Jeff Brown85297452011-03-04 13:07:49 -08003968 axis.axisInfo.axis = nextGenericAxisId;
Jeff Brown6f2fba42011-02-19 01:08:02 -08003969 nextGenericAxisId += 1;
3970 } else {
3971 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3972 "have already been assigned to other axes.",
3973 getDeviceName().string(), mAxes.keyAt(i));
3974 mAxes.removeItemsAt(i--);
3975 numAxes -= 1;
3976 }
3977 }
3978 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003979}
3980
Jeff Brown85297452011-03-04 13:07:49 -08003981bool JoystickInputMapper::haveAxis(int32_t axisId) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003982 size_t numAxes = mAxes.size();
3983 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08003984 const Axis& axis = mAxes.valueAt(i);
3985 if (axis.axisInfo.axis == axisId
3986 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
3987 && axis.axisInfo.highAxis == axisId)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08003988 return true;
3989 }
3990 }
3991 return false;
3992}
Jeff Browncb1404e2011-01-15 18:14:15 -08003993
Jeff Brown6f2fba42011-02-19 01:08:02 -08003994void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
3995 size_t i = mAxes.size();
3996 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
3997 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
3998 continue;
3999 }
4000 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
4001 getDeviceName().string(), mAxes.keyAt(i));
4002 mAxes.removeItemsAt(i);
4003 }
4004}
4005
4006bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
4007 switch (axis) {
4008 case AMOTION_EVENT_AXIS_X:
4009 case AMOTION_EVENT_AXIS_Y:
4010 case AMOTION_EVENT_AXIS_Z:
4011 case AMOTION_EVENT_AXIS_RX:
4012 case AMOTION_EVENT_AXIS_RY:
4013 case AMOTION_EVENT_AXIS_RZ:
4014 case AMOTION_EVENT_AXIS_HAT_X:
4015 case AMOTION_EVENT_AXIS_HAT_Y:
4016 case AMOTION_EVENT_AXIS_ORIENTATION:
Jeff Brown85297452011-03-04 13:07:49 -08004017 case AMOTION_EVENT_AXIS_RUDDER:
4018 case AMOTION_EVENT_AXIS_WHEEL:
Jeff Brown6f2fba42011-02-19 01:08:02 -08004019 return true;
4020 default:
4021 return false;
4022 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004023}
4024
4025void JoystickInputMapper::reset() {
4026 // Recenter all axes.
4027 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08004028
Jeff Brown6f2fba42011-02-19 01:08:02 -08004029 size_t numAxes = mAxes.size();
4030 for (size_t i = 0; i < numAxes; i++) {
4031 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08004032 axis.resetValue();
Jeff Brown6f2fba42011-02-19 01:08:02 -08004033 }
4034
4035 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08004036
4037 InputMapper::reset();
4038}
4039
4040void JoystickInputMapper::process(const RawEvent* rawEvent) {
4041 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004042 case EV_ABS: {
4043 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
4044 if (index >= 0) {
4045 Axis& axis = mAxes.editValueAt(index);
Jeff Brown85297452011-03-04 13:07:49 -08004046 float newValue, highNewValue;
4047 switch (axis.axisInfo.mode) {
4048 case AxisInfo::MODE_INVERT:
4049 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
4050 * axis.scale + axis.offset;
4051 highNewValue = 0.0f;
4052 break;
4053 case AxisInfo::MODE_SPLIT:
4054 if (rawEvent->value < axis.axisInfo.splitValue) {
4055 newValue = (axis.axisInfo.splitValue - rawEvent->value)
4056 * axis.scale + axis.offset;
4057 highNewValue = 0.0f;
4058 } else if (rawEvent->value > axis.axisInfo.splitValue) {
4059 newValue = 0.0f;
4060 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
4061 * axis.highScale + axis.highOffset;
4062 } else {
4063 newValue = 0.0f;
4064 highNewValue = 0.0f;
4065 }
4066 break;
4067 default:
4068 newValue = rawEvent->value * axis.scale + axis.offset;
4069 highNewValue = 0.0f;
4070 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004071 }
Jeff Brown85297452011-03-04 13:07:49 -08004072 axis.newValue = newValue;
4073 axis.highNewValue = highNewValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08004074 }
4075 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004076 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004077
4078 case EV_SYN:
4079 switch (rawEvent->scanCode) {
4080 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08004081 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08004082 break;
4083 }
4084 break;
4085 }
4086}
4087
Jeff Brown6f2fba42011-02-19 01:08:02 -08004088void JoystickInputMapper::sync(nsecs_t when, bool force) {
Jeff Brown85297452011-03-04 13:07:49 -08004089 if (!filterAxes(force)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004090 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08004091 }
4092
4093 int32_t metaState = mContext->getGlobalMetaState();
4094
Jeff Brown6f2fba42011-02-19 01:08:02 -08004095 PointerCoords pointerCoords;
4096 pointerCoords.clear();
4097
4098 size_t numAxes = mAxes.size();
4099 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08004100 const Axis& axis = mAxes.valueAt(i);
4101 pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
4102 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
4103 pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
4104 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004105 }
4106
Jeff Brown56194eb2011-03-02 19:23:13 -08004107 // Moving a joystick axis should not wake the devide because joysticks can
4108 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
4109 // button will likely wake the device.
4110 // TODO: Use the input device configuration to control this behavior more finely.
4111 uint32_t policyFlags = 0;
4112
Jeff Brown6f2fba42011-02-19 01:08:02 -08004113 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08004114 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brown6f2fba42011-02-19 01:08:02 -08004115 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
4116 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08004117}
4118
Jeff Brown85297452011-03-04 13:07:49 -08004119bool JoystickInputMapper::filterAxes(bool force) {
4120 bool atLeastOneSignificantChange = force;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004121 size_t numAxes = mAxes.size();
4122 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08004123 Axis& axis = mAxes.editValueAt(i);
4124 if (force || hasValueChangedSignificantly(axis.filter,
4125 axis.newValue, axis.currentValue, axis.min, axis.max)) {
4126 axis.currentValue = axis.newValue;
4127 atLeastOneSignificantChange = true;
4128 }
4129 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
4130 if (force || hasValueChangedSignificantly(axis.filter,
4131 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
4132 axis.highCurrentValue = axis.highNewValue;
4133 atLeastOneSignificantChange = true;
4134 }
4135 }
4136 }
4137 return atLeastOneSignificantChange;
4138}
4139
4140bool JoystickInputMapper::hasValueChangedSignificantly(
4141 float filter, float newValue, float currentValue, float min, float max) {
4142 if (newValue != currentValue) {
4143 // Filter out small changes in value unless the value is converging on the axis
4144 // bounds or center point. This is intended to reduce the amount of information
4145 // sent to applications by particularly noisy joysticks (such as PS3).
4146 if (fabs(newValue - currentValue) > filter
4147 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
4148 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
4149 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
4150 return true;
4151 }
4152 }
4153 return false;
4154}
4155
4156bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
4157 float filter, float newValue, float currentValue, float thresholdValue) {
4158 float newDistance = fabs(newValue - thresholdValue);
4159 if (newDistance < filter) {
4160 float oldDistance = fabs(currentValue - thresholdValue);
4161 if (newDistance < oldDistance) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004162 return true;
4163 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004164 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08004165 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08004166}
4167
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004168} // namespace android