blob: 577da01527ad2644e9dbc5e3242ff033c1f3bb03 [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036#include "InputReader.h"
37
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080039#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080040#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070045#include <errno.h>
46#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070047#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048
Jeff Brown8d608662010-08-30 03:02:23 -070049#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070050#define INDENT2 " "
51#define INDENT3 " "
52#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070053
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070054namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60 return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65 return a < b ? a : b;
66}
67
Jeff Brown5c225b12010-06-16 01:53:36 -070068template<typename T>
69inline static void swap(T& a, T& b) {
70 T temp = a;
71 a = b;
72 b = temp;
73}
74
Jeff Brown8d608662010-08-30 03:02:23 -070075inline static float avg(float x, float y) {
76 return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80 return sqrtf(x * x + y * y);
81}
82
Jeff Brown517bb4c2011-01-14 19:09:23 -080083inline static int32_t signExtendNybble(int32_t value) {
84 return value >= 8 ? value - 16 : value;
85}
86
Jeff Brownef3d7e82010-09-30 14:33:04 -070087static inline const char* toString(bool value) {
88 return value ? "true" : "false";
89}
90
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070091static const int32_t keyCodeRotationMap[][4] = {
92 // key codes enumerated counter-clockwise with the original (unrotated) key first
93 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -070094 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
95 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
96 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
97 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070098};
99static const int keyCodeRotationMapSize =
100 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
101
102int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103 if (orientation != DISPLAY_ORIENTATION_0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700104 for (int i = 0; i < keyCodeRotationMapSize; i++) {
105 if (keyCode == keyCodeRotationMap[i][0]) {
106 return keyCodeRotationMap[i][orientation];
107 }
108 }
109 }
110 return keyCode;
111}
112
Jeff Brown6d0fec22010-07-23 21:28:06 -0700113static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
114 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
115}
116
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700117
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700118// --- InputReader ---
119
120InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700121 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700122 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700123 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brownfe508922011-01-18 15:10:10 -0800124 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700125 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700126 updateGlobalMetaState();
127 updateInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700128}
129
130InputReader::~InputReader() {
131 for (size_t i = 0; i < mDevices.size(); i++) {
132 delete mDevices.valueAt(i);
133 }
134}
135
136void InputReader::loopOnce() {
137 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700138 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700139
140#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800141 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700142 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
143 rawEvent.value);
144#endif
145
146 process(& rawEvent);
147}
148
149void InputReader::process(const RawEvent* rawEvent) {
150 switch (rawEvent->type) {
151 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700152 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700153 break;
154
155 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700156 removeDevice(rawEvent->deviceId);
157 break;
158
159 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700160 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700161 break;
162
Jeff Brown6d0fec22010-07-23 21:28:06 -0700163 default:
164 consumeEvent(rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700165 break;
166 }
167}
168
Jeff Brown7342bb92010-10-01 18:55:43 -0700169void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700170 String8 name = mEventHub->getDeviceName(deviceId);
171 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
172
173 InputDevice* device = createDevice(deviceId, name, classes);
174 device->configure();
175
Jeff Brown8d608662010-08-30 03:02:23 -0700176 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800177 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700178 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800179 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700180 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700181 }
182
Jeff Brown6d0fec22010-07-23 21:28:06 -0700183 bool added = false;
184 { // acquire device registry writer lock
185 RWLock::AutoWLock _wl(mDeviceRegistryLock);
186
187 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
188 if (deviceIndex < 0) {
189 mDevices.add(deviceId, device);
190 added = true;
191 }
192 } // release device registry writer lock
193
194 if (! added) {
195 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
196 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700197 return;
198 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700199}
200
Jeff Brown7342bb92010-10-01 18:55:43 -0700201void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700202 bool removed = false;
203 InputDevice* device = NULL;
204 { // acquire device registry writer lock
205 RWLock::AutoWLock _wl(mDeviceRegistryLock);
206
207 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
208 if (deviceIndex >= 0) {
209 device = mDevices.valueAt(deviceIndex);
210 mDevices.removeItemsAt(deviceIndex, 1);
211 removed = true;
212 }
213 } // release device registry writer lock
214
215 if (! removed) {
216 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800221 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 device->getId(), device->getName().string());
223 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800224 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700225 device->getId(), device->getName().string(), device->getSources());
226 }
227
Jeff Brown8d608662010-08-30 03:02:23 -0700228 device->reset();
229
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700231}
232
Jeff Brown6d0fec22010-07-23 21:28:06 -0700233InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
234 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700235
Jeff Brown6d0fec22010-07-23 21:28:06 -0700236 // Switch-like devices.
237 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
238 device->addMapper(new SwitchInputMapper(device));
239 }
240
241 // Keyboard-like devices.
242 uint32_t keyboardSources = 0;
243 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
244 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
245 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
246 }
247 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
248 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
249 }
250 if (classes & INPUT_DEVICE_CLASS_DPAD) {
251 keyboardSources |= AINPUT_SOURCE_DPAD;
252 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800253 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
254 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
255 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700256
257 if (keyboardSources != 0) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800258 device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700259 }
260
Jeff Brown83c09682010-12-23 17:50:18 -0800261 // Cursor-like devices.
262 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
263 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700264 }
265
Jeff Brown58a2da82011-01-25 16:02:22 -0800266 // Touchscreens and touchpad devices.
267 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800268 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800269 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800270 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700271 }
272
Jeff Browncb1404e2011-01-15 18:14:15 -0800273 // Joystick-like devices.
274 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
275 device->addMapper(new JoystickInputMapper(device));
276 }
277
Jeff Brown6d0fec22010-07-23 21:28:06 -0700278 return device;
279}
280
281void InputReader::consumeEvent(const RawEvent* rawEvent) {
282 int32_t deviceId = rawEvent->deviceId;
283
284 { // acquire device registry reader lock
285 RWLock::AutoRLock _rl(mDeviceRegistryLock);
286
287 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
288 if (deviceIndex < 0) {
289 LOGW("Discarding event for unknown deviceId %d.", deviceId);
290 return;
291 }
292
293 InputDevice* device = mDevices.valueAt(deviceIndex);
294 if (device->isIgnored()) {
295 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
296 return;
297 }
298
299 device->process(rawEvent);
300 } // release device registry reader lock
301}
302
Jeff Brownc3db8582010-10-20 15:33:38 -0700303void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700304 // Reset global meta state because it depends on the list of all configured devices.
305 updateGlobalMetaState();
306
307 // Update input configuration.
308 updateInputConfiguration();
309
310 // Enqueue configuration changed.
311 mDispatcher->notifyConfigurationChanged(when);
312}
313
314void InputReader::configureExcludedDevices() {
315 Vector<String8> excludedDeviceNames;
316 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
317
318 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
319 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
320 }
321}
322
323void InputReader::updateGlobalMetaState() {
324 { // acquire state lock
325 AutoMutex _l(mStateLock);
326
327 mGlobalMetaState = 0;
328
329 { // acquire device registry reader lock
330 RWLock::AutoRLock _rl(mDeviceRegistryLock);
331
332 for (size_t i = 0; i < mDevices.size(); i++) {
333 InputDevice* device = mDevices.valueAt(i);
334 mGlobalMetaState |= device->getMetaState();
335 }
336 } // release device registry reader lock
337 } // release state lock
338}
339
340int32_t InputReader::getGlobalMetaState() {
341 { // acquire state lock
342 AutoMutex _l(mStateLock);
343
344 return mGlobalMetaState;
345 } // release state lock
346}
347
348void InputReader::updateInputConfiguration() {
349 { // acquire state lock
350 AutoMutex _l(mStateLock);
351
352 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
353 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
354 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
355 { // acquire device registry reader lock
356 RWLock::AutoRLock _rl(mDeviceRegistryLock);
357
358 InputDeviceInfo deviceInfo;
359 for (size_t i = 0; i < mDevices.size(); i++) {
360 InputDevice* device = mDevices.valueAt(i);
361 device->getDeviceInfo(& deviceInfo);
362 uint32_t sources = deviceInfo.getSources();
363
364 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
365 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
366 }
367 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
368 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
369 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
370 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
371 }
372 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
373 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700374 }
375 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700376 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700377
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 mInputConfiguration.touchScreen = touchScreenConfig;
379 mInputConfiguration.keyboard = keyboardConfig;
380 mInputConfiguration.navigation = navigationConfig;
381 } // release state lock
382}
383
Jeff Brownfe508922011-01-18 15:10:10 -0800384void InputReader::disableVirtualKeysUntil(nsecs_t time) {
385 mDisableVirtualKeysTimeout = time;
386}
387
388bool InputReader::shouldDropVirtualKey(nsecs_t now,
389 InputDevice* device, int32_t keyCode, int32_t scanCode) {
390 if (now < mDisableVirtualKeysTimeout) {
391 LOGI("Dropping virtual key from device %s because virtual keys are "
392 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
393 device->getName().string(),
394 (mDisableVirtualKeysTimeout - now) * 0.000001,
395 keyCode, scanCode);
396 return true;
397 } else {
398 return false;
399 }
400}
401
Jeff Brown6d0fec22010-07-23 21:28:06 -0700402void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
403 { // acquire state lock
404 AutoMutex _l(mStateLock);
405
406 *outConfiguration = mInputConfiguration;
407 } // release state lock
408}
409
410status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
411 { // acquire device registry reader lock
412 RWLock::AutoRLock _rl(mDeviceRegistryLock);
413
414 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
415 if (deviceIndex < 0) {
416 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700417 }
418
Jeff Brown6d0fec22010-07-23 21:28:06 -0700419 InputDevice* device = mDevices.valueAt(deviceIndex);
420 if (device->isIgnored()) {
421 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700422 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700423
424 device->getDeviceInfo(outDeviceInfo);
425 return OK;
426 } // release device registy reader lock
427}
428
429void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
430 outDeviceIds.clear();
431
432 { // acquire device registry reader lock
433 RWLock::AutoRLock _rl(mDeviceRegistryLock);
434
435 size_t numDevices = mDevices.size();
436 for (size_t i = 0; i < numDevices; i++) {
437 InputDevice* device = mDevices.valueAt(i);
438 if (! device->isIgnored()) {
439 outDeviceIds.add(device->getId());
440 }
441 }
442 } // release device registy reader lock
443}
444
445int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
446 int32_t keyCode) {
447 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
448}
449
450int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
451 int32_t scanCode) {
452 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
453}
454
455int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
456 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
457}
458
459int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
460 GetStateFunc getStateFunc) {
461 { // acquire device registry reader lock
462 RWLock::AutoRLock _rl(mDeviceRegistryLock);
463
464 int32_t result = AKEY_STATE_UNKNOWN;
465 if (deviceId >= 0) {
466 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
467 if (deviceIndex >= 0) {
468 InputDevice* device = mDevices.valueAt(deviceIndex);
469 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
470 result = (device->*getStateFunc)(sourceMask, code);
471 }
472 }
473 } else {
474 size_t numDevices = mDevices.size();
475 for (size_t i = 0; i < numDevices; i++) {
476 InputDevice* device = mDevices.valueAt(i);
477 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
478 result = (device->*getStateFunc)(sourceMask, code);
479 if (result >= AKEY_STATE_DOWN) {
480 return result;
481 }
482 }
483 }
484 }
485 return result;
486 } // release device registy reader lock
487}
488
489bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
490 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
491 memset(outFlags, 0, numCodes);
492 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
493}
494
495bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
496 const int32_t* keyCodes, uint8_t* outFlags) {
497 { // acquire device registry reader lock
498 RWLock::AutoRLock _rl(mDeviceRegistryLock);
499 bool result = false;
500 if (deviceId >= 0) {
501 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
502 if (deviceIndex >= 0) {
503 InputDevice* device = mDevices.valueAt(deviceIndex);
504 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
505 result = device->markSupportedKeyCodes(sourceMask,
506 numCodes, keyCodes, outFlags);
507 }
508 }
509 } else {
510 size_t numDevices = mDevices.size();
511 for (size_t i = 0; i < numDevices; i++) {
512 InputDevice* device = mDevices.valueAt(i);
513 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
514 result |= device->markSupportedKeyCodes(sourceMask,
515 numCodes, keyCodes, outFlags);
516 }
517 }
518 }
519 return result;
520 } // release device registy reader lock
521}
522
Jeff Brownb88102f2010-09-08 11:49:43 -0700523void InputReader::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -0700524 mEventHub->dump(dump);
525 dump.append("\n");
526
527 dump.append("Input Reader State:\n");
528
Jeff Brownef3d7e82010-09-30 14:33:04 -0700529 { // acquire device registry reader lock
530 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700531
Jeff Brownef3d7e82010-09-30 14:33:04 -0700532 for (size_t i = 0; i < mDevices.size(); i++) {
533 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700534 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700535 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700536}
537
Jeff Brown6d0fec22010-07-23 21:28:06 -0700538
539// --- InputReaderThread ---
540
541InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
542 Thread(/*canCallJava*/ true), mReader(reader) {
543}
544
545InputReaderThread::~InputReaderThread() {
546}
547
548bool InputReaderThread::threadLoop() {
549 mReader->loopOnce();
550 return true;
551}
552
553
554// --- InputDevice ---
555
556InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
557 mContext(context), mId(id), mName(name), mSources(0) {
558}
559
560InputDevice::~InputDevice() {
561 size_t numMappers = mMappers.size();
562 for (size_t i = 0; i < numMappers; i++) {
563 delete mMappers[i];
564 }
565 mMappers.clear();
566}
567
Jeff Brownef3d7e82010-09-30 14:33:04 -0700568static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
569 int32_t rangeType, const char* name) {
570 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
571 if (range) {
572 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
573 name, range->min, range->max, range->flat, range->fuzz);
574 }
575}
576
577void InputDevice::dump(String8& dump) {
578 InputDeviceInfo deviceInfo;
579 getDeviceInfo(& deviceInfo);
580
Jeff Brown90655042010-12-02 13:50:46 -0800581 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700582 deviceInfo.getName().string());
583 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
584 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
585 if (!deviceInfo.getMotionRanges().isEmpty()) {
586 dump.append(INDENT2 "Motion Ranges:\n");
587 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
588 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
589 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
590 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
591 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
592 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
593 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
594 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
595 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
596 }
597
598 size_t numMappers = mMappers.size();
599 for (size_t i = 0; i < numMappers; i++) {
600 InputMapper* mapper = mMappers[i];
601 mapper->dump(dump);
602 }
603}
604
Jeff Brown6d0fec22010-07-23 21:28:06 -0700605void InputDevice::addMapper(InputMapper* mapper) {
606 mMappers.add(mapper);
607}
608
609void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700610 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800611 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700612 }
613
Jeff Brown6d0fec22010-07-23 21:28:06 -0700614 mSources = 0;
615
616 size_t numMappers = mMappers.size();
617 for (size_t i = 0; i < numMappers; i++) {
618 InputMapper* mapper = mMappers[i];
619 mapper->configure();
620 mSources |= mapper->getSources();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700621 }
622}
623
Jeff Brown6d0fec22010-07-23 21:28:06 -0700624void InputDevice::reset() {
625 size_t numMappers = mMappers.size();
626 for (size_t i = 0; i < numMappers; i++) {
627 InputMapper* mapper = mMappers[i];
628 mapper->reset();
629 }
630}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700631
Jeff Brown6d0fec22010-07-23 21:28:06 -0700632void InputDevice::process(const RawEvent* rawEvent) {
633 size_t numMappers = mMappers.size();
634 for (size_t i = 0; i < numMappers; i++) {
635 InputMapper* mapper = mMappers[i];
636 mapper->process(rawEvent);
637 }
638}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700639
Jeff Brown6d0fec22010-07-23 21:28:06 -0700640void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
641 outDeviceInfo->initialize(mId, mName);
642
643 size_t numMappers = mMappers.size();
644 for (size_t i = 0; i < numMappers; i++) {
645 InputMapper* mapper = mMappers[i];
646 mapper->populateDeviceInfo(outDeviceInfo);
647 }
648}
649
650int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
651 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
652}
653
654int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
655 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
656}
657
658int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
659 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
660}
661
662int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
663 int32_t result = AKEY_STATE_UNKNOWN;
664 size_t numMappers = mMappers.size();
665 for (size_t i = 0; i < numMappers; i++) {
666 InputMapper* mapper = mMappers[i];
667 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
668 result = (mapper->*getStateFunc)(sourceMask, code);
669 if (result >= AKEY_STATE_DOWN) {
670 return result;
671 }
672 }
673 }
674 return result;
675}
676
677bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
678 const int32_t* keyCodes, uint8_t* outFlags) {
679 bool result = false;
680 size_t numMappers = mMappers.size();
681 for (size_t i = 0; i < numMappers; i++) {
682 InputMapper* mapper = mMappers[i];
683 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
684 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
685 }
686 }
687 return result;
688}
689
690int32_t InputDevice::getMetaState() {
691 int32_t result = 0;
692 size_t numMappers = mMappers.size();
693 for (size_t i = 0; i < numMappers; i++) {
694 InputMapper* mapper = mMappers[i];
695 result |= mapper->getMetaState();
696 }
697 return result;
698}
699
700
701// --- InputMapper ---
702
703InputMapper::InputMapper(InputDevice* device) :
704 mDevice(device), mContext(device->getContext()) {
705}
706
707InputMapper::~InputMapper() {
708}
709
710void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
711 info->addSource(getSources());
712}
713
Jeff Brownef3d7e82010-09-30 14:33:04 -0700714void InputMapper::dump(String8& dump) {
715}
716
Jeff Brown6d0fec22010-07-23 21:28:06 -0700717void InputMapper::configure() {
718}
719
720void InputMapper::reset() {
721}
722
723int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
724 return AKEY_STATE_UNKNOWN;
725}
726
727int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
728 return AKEY_STATE_UNKNOWN;
729}
730
731int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
732 return AKEY_STATE_UNKNOWN;
733}
734
735bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
736 const int32_t* keyCodes, uint8_t* outFlags) {
737 return false;
738}
739
740int32_t InputMapper::getMetaState() {
741 return 0;
742}
743
Jeff Browncb1404e2011-01-15 18:14:15 -0800744void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
745 const RawAbsoluteAxisInfo& axis, const char* name) {
746 if (axis.valid) {
747 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
748 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
749 } else {
750 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
751 }
752}
753
Jeff Brown6d0fec22010-07-23 21:28:06 -0700754
755// --- SwitchInputMapper ---
756
757SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
758 InputMapper(device) {
759}
760
761SwitchInputMapper::~SwitchInputMapper() {
762}
763
764uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800765 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700766}
767
768void SwitchInputMapper::process(const RawEvent* rawEvent) {
769 switch (rawEvent->type) {
770 case EV_SW:
771 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
772 break;
773 }
774}
775
776void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700777 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700778}
779
780int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
781 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
782}
783
784
785// --- KeyboardInputMapper ---
786
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800787KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700788 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800789 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700790 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700791 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700792}
793
794KeyboardInputMapper::~KeyboardInputMapper() {
795}
796
Jeff Brown6328cdc2010-07-29 18:18:33 -0700797void KeyboardInputMapper::initializeLocked() {
798 mLocked.metaState = AMETA_NONE;
799 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700800}
801
802uint32_t KeyboardInputMapper::getSources() {
803 return mSources;
804}
805
806void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
807 InputMapper::populateDeviceInfo(info);
808
809 info->setKeyboardType(mKeyboardType);
810}
811
Jeff Brownef3d7e82010-09-30 14:33:04 -0700812void KeyboardInputMapper::dump(String8& dump) {
813 { // acquire lock
814 AutoMutex _l(mLock);
815 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800816 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700817 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
818 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
819 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
820 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
821 } // release lock
822}
823
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800824
825void KeyboardInputMapper::configure() {
826 InputMapper::configure();
827
828 // Configure basic parameters.
829 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800830
831 // Reset LEDs.
832 {
833 AutoMutex _l(mLock);
834 resetLedStateLocked();
835 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800836}
837
838void KeyboardInputMapper::configureParameters() {
839 mParameters.orientationAware = false;
840 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
841 mParameters.orientationAware);
842
843 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
844}
845
846void KeyboardInputMapper::dumpParameters(String8& dump) {
847 dump.append(INDENT3 "Parameters:\n");
848 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
849 mParameters.associatedDisplayId);
850 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
851 toString(mParameters.orientationAware));
852}
853
Jeff Brown6d0fec22010-07-23 21:28:06 -0700854void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700855 for (;;) {
856 int32_t keyCode, scanCode;
857 { // acquire lock
858 AutoMutex _l(mLock);
859
860 // Synthesize key up event on reset if keys are currently down.
861 if (mLocked.keyDowns.isEmpty()) {
862 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800863 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700864 break; // done
865 }
866
867 const KeyDown& keyDown = mLocked.keyDowns.top();
868 keyCode = keyDown.keyCode;
869 scanCode = keyDown.scanCode;
870 } // release lock
871
Jeff Brown6d0fec22010-07-23 21:28:06 -0700872 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700873 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700874 }
875
876 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700877 getContext()->updateGlobalMetaState();
878}
879
880void KeyboardInputMapper::process(const RawEvent* rawEvent) {
881 switch (rawEvent->type) {
882 case EV_KEY: {
883 int32_t scanCode = rawEvent->scanCode;
884 if (isKeyboardOrGamepadKey(scanCode)) {
885 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
886 rawEvent->flags);
887 }
888 break;
889 }
890 }
891}
892
893bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
894 return scanCode < BTN_MOUSE
895 || scanCode >= KEY_OK
Jeff Browncb1404e2011-01-15 18:14:15 -0800896 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700897}
898
Jeff Brown6328cdc2010-07-29 18:18:33 -0700899void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
900 int32_t scanCode, uint32_t policyFlags) {
901 int32_t newMetaState;
902 nsecs_t downTime;
903 bool metaStateChanged = false;
904
905 { // acquire lock
906 AutoMutex _l(mLock);
907
908 if (down) {
909 // Rotate key codes according to orientation if needed.
910 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800911 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700912 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800913 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
914 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800915 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700916 }
917
918 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700919 }
920
Jeff Brown6328cdc2010-07-29 18:18:33 -0700921 // Add key down.
922 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
923 if (keyDownIndex >= 0) {
924 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800925 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700926 } else {
927 // key down
Jeff Brownfe508922011-01-18 15:10:10 -0800928 if ((policyFlags & POLICY_FLAG_VIRTUAL)
929 && mContext->shouldDropVirtualKey(when,
930 getDevice(), keyCode, scanCode)) {
931 return;
932 }
933
Jeff Brown6328cdc2010-07-29 18:18:33 -0700934 mLocked.keyDowns.push();
935 KeyDown& keyDown = mLocked.keyDowns.editTop();
936 keyDown.keyCode = keyCode;
937 keyDown.scanCode = scanCode;
938 }
939
940 mLocked.downTime = when;
941 } else {
942 // Remove key down.
943 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
944 if (keyDownIndex >= 0) {
945 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800946 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700947 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
948 } else {
949 // key was not actually down
950 LOGI("Dropping key up from device %s because the key was not down. "
951 "keyCode=%d, scanCode=%d",
952 getDeviceName().string(), keyCode, scanCode);
953 return;
954 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700955 }
956
Jeff Brown6328cdc2010-07-29 18:18:33 -0700957 int32_t oldMetaState = mLocked.metaState;
958 newMetaState = updateMetaState(keyCode, down, oldMetaState);
959 if (oldMetaState != newMetaState) {
960 mLocked.metaState = newMetaState;
961 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -0700962 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700963 }
Jeff Brownfd0358292010-06-30 16:10:35 -0700964
Jeff Brown6328cdc2010-07-29 18:18:33 -0700965 downTime = mLocked.downTime;
966 } // release lock
967
968 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700969 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700970 }
971
Jeff Brown497a92c2010-09-12 17:55:08 -0700972 if (policyFlags & POLICY_FLAG_FUNCTION) {
973 newMetaState |= AMETA_FUNCTION_ON;
974 }
Jeff Brown83c09682010-12-23 17:50:18 -0800975 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -0700976 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
977 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700978}
979
Jeff Brown6328cdc2010-07-29 18:18:33 -0700980ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
981 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700982 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700983 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700984 return i;
985 }
986 }
987 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700988}
989
Jeff Brown6d0fec22010-07-23 21:28:06 -0700990int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
991 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
992}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700993
Jeff Brown6d0fec22010-07-23 21:28:06 -0700994int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
995 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
996}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700997
Jeff Brown6d0fec22010-07-23 21:28:06 -0700998bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
999 const int32_t* keyCodes, uint8_t* outFlags) {
1000 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1001}
1002
1003int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001004 { // acquire lock
1005 AutoMutex _l(mLock);
1006 return mLocked.metaState;
1007 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001008}
1009
Jeff Brown49ed71d2010-12-06 17:13:33 -08001010void KeyboardInputMapper::resetLedStateLocked() {
1011 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1012 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1013 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1014
1015 updateLedStateLocked(true);
1016}
1017
1018void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1019 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1020 ledState.on = false;
1021}
1022
Jeff Brown497a92c2010-09-12 17:55:08 -07001023void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1024 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001025 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001026 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001027 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001028 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001029 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001030}
1031
1032void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1033 int32_t led, int32_t modifier, bool reset) {
1034 if (ledState.avail) {
1035 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001036 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001037 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1038 ledState.on = desiredState;
1039 }
1040 }
1041}
1042
Jeff Brown6d0fec22010-07-23 21:28:06 -07001043
Jeff Brown83c09682010-12-23 17:50:18 -08001044// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001045
Jeff Brown83c09682010-12-23 17:50:18 -08001046CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001047 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001048 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001049}
1050
Jeff Brown83c09682010-12-23 17:50:18 -08001051CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001052}
1053
Jeff Brown83c09682010-12-23 17:50:18 -08001054uint32_t CursorInputMapper::getSources() {
1055 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001056}
1057
Jeff Brown83c09682010-12-23 17:50:18 -08001058void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001059 InputMapper::populateDeviceInfo(info);
1060
Jeff Brown83c09682010-12-23 17:50:18 -08001061 if (mParameters.mode == Parameters::MODE_POINTER) {
1062 float minX, minY, maxX, maxY;
1063 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1064 info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f);
1065 info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f);
1066 }
1067 } else {
1068 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1069 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1070 }
1071 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001072}
1073
Jeff Brown83c09682010-12-23 17:50:18 -08001074void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001075 { // acquire lock
1076 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001077 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001078 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001079 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1080 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1081 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1082 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1083 } // release lock
1084}
1085
Jeff Brown83c09682010-12-23 17:50:18 -08001086void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001087 InputMapper::configure();
1088
1089 // Configure basic parameters.
1090 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001091
1092 // Configure device mode.
1093 switch (mParameters.mode) {
1094 case Parameters::MODE_POINTER:
1095 mSources = AINPUT_SOURCE_MOUSE;
1096 mXPrecision = 1.0f;
1097 mYPrecision = 1.0f;
1098 mXScale = 1.0f;
1099 mYScale = 1.0f;
1100 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1101 break;
1102 case Parameters::MODE_NAVIGATION:
1103 mSources = AINPUT_SOURCE_TRACKBALL;
1104 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1105 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1106 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1107 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1108 break;
1109 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001110}
1111
Jeff Brown83c09682010-12-23 17:50:18 -08001112void CursorInputMapper::configureParameters() {
1113 mParameters.mode = Parameters::MODE_POINTER;
1114 String8 cursorModeString;
1115 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1116 if (cursorModeString == "navigation") {
1117 mParameters.mode = Parameters::MODE_NAVIGATION;
1118 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1119 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1120 }
1121 }
1122
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001123 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001124 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001125 mParameters.orientationAware);
1126
Jeff Brown83c09682010-12-23 17:50:18 -08001127 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1128 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001129}
1130
Jeff Brown83c09682010-12-23 17:50:18 -08001131void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001132 dump.append(INDENT3 "Parameters:\n");
1133 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1134 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001135
1136 switch (mParameters.mode) {
1137 case Parameters::MODE_POINTER:
1138 dump.append(INDENT4 "Mode: pointer\n");
1139 break;
1140 case Parameters::MODE_NAVIGATION:
1141 dump.append(INDENT4 "Mode: navigation\n");
1142 break;
1143 default:
1144 assert(false);
1145 }
1146
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001147 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1148 toString(mParameters.orientationAware));
1149}
1150
Jeff Brown83c09682010-12-23 17:50:18 -08001151void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001152 mAccumulator.clear();
1153
Jeff Brown6328cdc2010-07-29 18:18:33 -07001154 mLocked.down = false;
1155 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001156}
1157
Jeff Brown83c09682010-12-23 17:50:18 -08001158void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001159 for (;;) {
1160 { // acquire lock
1161 AutoMutex _l(mLock);
1162
1163 if (! mLocked.down) {
1164 initializeLocked();
1165 break; // done
1166 }
1167 } // release lock
1168
Jeff Brown83c09682010-12-23 17:50:18 -08001169 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001170 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001171 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001172 mAccumulator.btnMouse = false;
1173 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001174 }
1175
Jeff Brown6d0fec22010-07-23 21:28:06 -07001176 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001177}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001178
Jeff Brown83c09682010-12-23 17:50:18 -08001179void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001180 switch (rawEvent->type) {
1181 case EV_KEY:
1182 switch (rawEvent->scanCode) {
1183 case BTN_MOUSE:
1184 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1185 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001186 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1187 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001188 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001189 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001190 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001191 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001192
Jeff Brown6d0fec22010-07-23 21:28:06 -07001193 case EV_REL:
1194 switch (rawEvent->scanCode) {
1195 case REL_X:
1196 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1197 mAccumulator.relX = rawEvent->value;
1198 break;
1199 case REL_Y:
1200 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1201 mAccumulator.relY = rawEvent->value;
1202 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001203 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001204 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001205
Jeff Brown6d0fec22010-07-23 21:28:06 -07001206 case EV_SYN:
1207 switch (rawEvent->scanCode) {
1208 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001209 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001210 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001211 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001212 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001213 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001214}
1215
Jeff Brown83c09682010-12-23 17:50:18 -08001216void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001217 uint32_t fields = mAccumulator.fields;
1218 if (fields == 0) {
1219 return; // no new state changes, so nothing to do
1220 }
1221
Jeff Brown6328cdc2010-07-29 18:18:33 -07001222 int motionEventAction;
1223 PointerCoords pointerCoords;
1224 nsecs_t downTime;
1225 { // acquire lock
1226 AutoMutex _l(mLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001227
Jeff Brown6328cdc2010-07-29 18:18:33 -07001228 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1229
1230 if (downChanged) {
1231 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001232 if (!mLocked.down) {
1233 mLocked.down = true;
1234 mLocked.downTime = when;
1235 } else {
1236 downChanged = false;
1237 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001238 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001239 if (mLocked.down) {
1240 mLocked.down = false;
1241 } else {
1242 downChanged = false;
1243 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001244 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001245 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001246
Jeff Brown6328cdc2010-07-29 18:18:33 -07001247 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001248 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1249 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001250
Jeff Brown6328cdc2010-07-29 18:18:33 -07001251 if (downChanged) {
1252 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001253 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001254 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001255 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001256
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001257 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001258 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001259 // Rotate motion based on display orientation if needed.
1260 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1261 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001262 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1263 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001264 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001265 }
1266
1267 float temp;
1268 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001269 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001270 temp = deltaX;
1271 deltaX = deltaY;
1272 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001273 break;
1274
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001275 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001276 deltaX = -deltaX;
1277 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001278 break;
1279
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001280 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001281 temp = deltaX;
1282 deltaX = -deltaY;
1283 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001284 break;
1285 }
1286 }
Jeff Brown83c09682010-12-23 17:50:18 -08001287
Jeff Brown91c69ab2011-02-14 17:03:18 -08001288 pointerCoords.clear();
1289
Jeff Brown83c09682010-12-23 17:50:18 -08001290 if (mPointerController != NULL) {
1291 mPointerController->move(deltaX, deltaY);
1292 if (downChanged) {
1293 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1294 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08001295 float x, y;
1296 mPointerController->getPosition(&x, &y);
1297 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_X, x);
1298 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_Y, y);
Jeff Brown83c09682010-12-23 17:50:18 -08001299 } else {
Jeff Brown91c69ab2011-02-14 17:03:18 -08001300 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_X, deltaX);
1301 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001302 }
1303
Jeff Brown91c69ab2011-02-14 17:03:18 -08001304 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001305 } // release lock
1306
Jeff Brown6d0fec22010-07-23 21:28:06 -07001307 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001308 int32_t pointerId = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001309 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
Jeff Brown85a31762010-09-01 17:01:00 -07001310 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001311 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1312
1313 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001314}
1315
Jeff Brown83c09682010-12-23 17:50:18 -08001316int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001317 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1318 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1319 } else {
1320 return AKEY_STATE_UNKNOWN;
1321 }
1322}
1323
Jeff Brown6d0fec22010-07-23 21:28:06 -07001324
1325// --- TouchInputMapper ---
1326
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001327TouchInputMapper::TouchInputMapper(InputDevice* device) :
1328 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001329 mLocked.surfaceOrientation = -1;
1330 mLocked.surfaceWidth = -1;
1331 mLocked.surfaceHeight = -1;
1332
1333 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001334}
1335
1336TouchInputMapper::~TouchInputMapper() {
1337}
1338
1339uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001340 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001341}
1342
1343void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1344 InputMapper::populateDeviceInfo(info);
1345
Jeff Brown6328cdc2010-07-29 18:18:33 -07001346 { // acquire lock
1347 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001348
Jeff Brown6328cdc2010-07-29 18:18:33 -07001349 // Ensure surface information is up to date so that orientation changes are
1350 // noticed immediately.
1351 configureSurfaceLocked();
1352
1353 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1354 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001355
1356 if (mLocked.orientedRanges.havePressure) {
1357 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1358 mLocked.orientedRanges.pressure);
1359 }
1360
1361 if (mLocked.orientedRanges.haveSize) {
1362 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1363 mLocked.orientedRanges.size);
1364 }
1365
Jeff Brownc6d282b2010-10-14 21:42:15 -07001366 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown8d608662010-08-30 03:02:23 -07001367 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1368 mLocked.orientedRanges.touchMajor);
1369 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1370 mLocked.orientedRanges.touchMinor);
1371 }
1372
Jeff Brownc6d282b2010-10-14 21:42:15 -07001373 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown8d608662010-08-30 03:02:23 -07001374 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1375 mLocked.orientedRanges.toolMajor);
1376 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1377 mLocked.orientedRanges.toolMinor);
1378 }
1379
1380 if (mLocked.orientedRanges.haveOrientation) {
1381 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1382 mLocked.orientedRanges.orientation);
1383 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001384 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001385}
1386
Jeff Brownef3d7e82010-09-30 14:33:04 -07001387void TouchInputMapper::dump(String8& dump) {
1388 { // acquire lock
1389 AutoMutex _l(mLock);
1390 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001391 dumpParameters(dump);
1392 dumpVirtualKeysLocked(dump);
1393 dumpRawAxes(dump);
1394 dumpCalibration(dump);
1395 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001396 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001397 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1398 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1399 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1400 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1401 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1402 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1403 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1404 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1405 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1406 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1407 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1408 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1409 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1410 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001411 } // release lock
1412}
1413
Jeff Brown6328cdc2010-07-29 18:18:33 -07001414void TouchInputMapper::initializeLocked() {
1415 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001416 mLastTouch.clear();
1417 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001418
1419 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1420 mAveragingTouchFilter.historyStart[i] = 0;
1421 mAveragingTouchFilter.historyEnd[i] = 0;
1422 }
1423
1424 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001425
1426 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001427
1428 mLocked.orientedRanges.havePressure = false;
1429 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001430 mLocked.orientedRanges.haveTouchSize = false;
1431 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001432 mLocked.orientedRanges.haveOrientation = false;
1433}
1434
Jeff Brown6d0fec22010-07-23 21:28:06 -07001435void TouchInputMapper::configure() {
1436 InputMapper::configure();
1437
1438 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001439 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001440
Jeff Brown83c09682010-12-23 17:50:18 -08001441 // Configure sources.
1442 switch (mParameters.deviceType) {
1443 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1444 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1445 break;
1446 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1447 mSources = AINPUT_SOURCE_TOUCHPAD;
1448 break;
1449 default:
1450 assert(false);
1451 }
1452
Jeff Brown6d0fec22010-07-23 21:28:06 -07001453 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001454 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001455
1456 // Prepare input device calibration.
1457 parseCalibration();
1458 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001459
Jeff Brown6328cdc2010-07-29 18:18:33 -07001460 { // acquire lock
1461 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001462
Jeff Brown8d608662010-08-30 03:02:23 -07001463 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001464 configureSurfaceLocked();
1465 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001466}
1467
Jeff Brown8d608662010-08-30 03:02:23 -07001468void TouchInputMapper::configureParameters() {
1469 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1470 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1471 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001472 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001473
1474 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001475 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001476 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1477 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001478 if (deviceTypeString == "touchScreen") {
1479 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1480 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001481 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1482 }
1483 }
1484 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1485
1486 mParameters.orientationAware = isTouchScreen;
1487 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1488 mParameters.orientationAware);
1489
1490 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001491}
1492
Jeff Brownef3d7e82010-09-30 14:33:04 -07001493void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001494 dump.append(INDENT3 "Parameters:\n");
1495
1496 switch (mParameters.deviceType) {
1497 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1498 dump.append(INDENT4 "DeviceType: touchScreen\n");
1499 break;
1500 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1501 dump.append(INDENT4 "DeviceType: touchPad\n");
1502 break;
1503 default:
1504 assert(false);
1505 }
1506
1507 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1508 mParameters.associatedDisplayId);
1509 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1510 toString(mParameters.orientationAware));
1511
1512 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001513 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001514 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001515 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001516 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001517 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001518}
1519
Jeff Brown8d608662010-08-30 03:02:23 -07001520void TouchInputMapper::configureRawAxes() {
1521 mRawAxes.x.clear();
1522 mRawAxes.y.clear();
1523 mRawAxes.pressure.clear();
1524 mRawAxes.touchMajor.clear();
1525 mRawAxes.touchMinor.clear();
1526 mRawAxes.toolMajor.clear();
1527 mRawAxes.toolMinor.clear();
1528 mRawAxes.orientation.clear();
1529}
1530
Jeff Brownef3d7e82010-09-30 14:33:04 -07001531void TouchInputMapper::dumpRawAxes(String8& dump) {
1532 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001533 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1534 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1535 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1536 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1537 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1538 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1539 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1540 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001541}
1542
Jeff Brown6328cdc2010-07-29 18:18:33 -07001543bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001544 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001545 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001546 int32_t width = mRawAxes.x.getRange();
1547 int32_t height = mRawAxes.y.getRange();
1548
1549 if (mParameters.associatedDisplayId >= 0) {
1550 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1551 bool wantOrientation = mParameters.orientationAware;
1552
Jeff Brown6328cdc2010-07-29 18:18:33 -07001553 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001554 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1555 wantSize ? &width : NULL, wantSize ? &height : NULL,
1556 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001557 return false;
1558 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001559 }
1560
Jeff Brown6328cdc2010-07-29 18:18:33 -07001561 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001562 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001563 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001564 }
1565
Jeff Brown6328cdc2010-07-29 18:18:33 -07001566 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001567 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001568 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001569 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001570
Jeff Brown6328cdc2010-07-29 18:18:33 -07001571 mLocked.surfaceWidth = width;
1572 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001573
Jeff Brown8d608662010-08-30 03:02:23 -07001574 // Configure X and Y factors.
1575 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001576 mLocked.xOrigin = mCalibration.haveXOrigin
1577 ? mCalibration.xOrigin
1578 : mRawAxes.x.minValue;
1579 mLocked.yOrigin = mCalibration.haveYOrigin
1580 ? mCalibration.yOrigin
1581 : mRawAxes.y.minValue;
1582 mLocked.xScale = mCalibration.haveXScale
1583 ? mCalibration.xScale
1584 : float(width) / mRawAxes.x.getRange();
1585 mLocked.yScale = mCalibration.haveYScale
1586 ? mCalibration.yScale
1587 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001588 mLocked.xPrecision = 1.0f / mLocked.xScale;
1589 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001590
Jeff Brown6328cdc2010-07-29 18:18:33 -07001591 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001592 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001593 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001594 mLocked.xOrigin = 0;
1595 mLocked.yOrigin = 0;
1596 mLocked.xScale = 1.0f;
1597 mLocked.yScale = 1.0f;
1598 mLocked.xPrecision = 1.0f;
1599 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001600 }
1601
Jeff Brown8d608662010-08-30 03:02:23 -07001602 // Scale factor for terms that are not oriented in a particular axis.
1603 // If the pixels are square then xScale == yScale otherwise we fake it
1604 // by choosing an average.
1605 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001606
Jeff Brown8d608662010-08-30 03:02:23 -07001607 // Size of diagonal axis.
1608 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001609
Jeff Brown8d608662010-08-30 03:02:23 -07001610 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001611 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1612 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001613 mLocked.orientedRanges.touchMajor.min = 0;
1614 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1615 mLocked.orientedRanges.touchMajor.flat = 0;
1616 mLocked.orientedRanges.touchMajor.fuzz = 0;
1617 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1618 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001619
Jeff Brown8d608662010-08-30 03:02:23 -07001620 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001621 mLocked.toolSizeLinearScale = 0;
1622 mLocked.toolSizeLinearBias = 0;
1623 mLocked.toolSizeAreaScale = 0;
1624 mLocked.toolSizeAreaBias = 0;
1625 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1626 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1627 if (mCalibration.haveToolSizeLinearScale) {
1628 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001629 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001630 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001631 / mRawAxes.toolMajor.maxValue;
1632 }
1633
Jeff Brownc6d282b2010-10-14 21:42:15 -07001634 if (mCalibration.haveToolSizeLinearBias) {
1635 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1636 }
1637 } else if (mCalibration.toolSizeCalibration ==
1638 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1639 if (mCalibration.haveToolSizeLinearScale) {
1640 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1641 } else {
1642 mLocked.toolSizeLinearScale = min(width, height);
1643 }
1644
1645 if (mCalibration.haveToolSizeLinearBias) {
1646 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1647 }
1648
1649 if (mCalibration.haveToolSizeAreaScale) {
1650 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1651 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1652 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1653 }
1654
1655 if (mCalibration.haveToolSizeAreaBias) {
1656 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001657 }
1658 }
1659
Jeff Brownc6d282b2010-10-14 21:42:15 -07001660 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001661 mLocked.orientedRanges.toolMajor.min = 0;
1662 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1663 mLocked.orientedRanges.toolMajor.flat = 0;
1664 mLocked.orientedRanges.toolMajor.fuzz = 0;
1665 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1666 }
1667
1668 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001669 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001670 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1671 RawAbsoluteAxisInfo rawPressureAxis;
1672 switch (mCalibration.pressureSource) {
1673 case Calibration::PRESSURE_SOURCE_PRESSURE:
1674 rawPressureAxis = mRawAxes.pressure;
1675 break;
1676 case Calibration::PRESSURE_SOURCE_TOUCH:
1677 rawPressureAxis = mRawAxes.touchMajor;
1678 break;
1679 default:
1680 rawPressureAxis.clear();
1681 }
1682
Jeff Brown8d608662010-08-30 03:02:23 -07001683 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1684 || mCalibration.pressureCalibration
1685 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1686 if (mCalibration.havePressureScale) {
1687 mLocked.pressureScale = mCalibration.pressureScale;
1688 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1689 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1690 }
1691 }
1692
1693 mLocked.orientedRanges.havePressure = true;
1694 mLocked.orientedRanges.pressure.min = 0;
1695 mLocked.orientedRanges.pressure.max = 1.0;
1696 mLocked.orientedRanges.pressure.flat = 0;
1697 mLocked.orientedRanges.pressure.fuzz = 0;
1698 }
1699
1700 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001701 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001702 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001703 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1704 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1705 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1706 }
1707 }
1708
1709 mLocked.orientedRanges.haveSize = true;
1710 mLocked.orientedRanges.size.min = 0;
1711 mLocked.orientedRanges.size.max = 1.0;
1712 mLocked.orientedRanges.size.flat = 0;
1713 mLocked.orientedRanges.size.fuzz = 0;
1714 }
1715
1716 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001717 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001718 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001719 if (mCalibration.orientationCalibration
1720 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1721 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1722 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1723 }
1724 }
1725
1726 mLocked.orientedRanges.orientation.min = - M_PI_2;
1727 mLocked.orientedRanges.orientation.max = M_PI_2;
1728 mLocked.orientedRanges.orientation.flat = 0;
1729 mLocked.orientedRanges.orientation.fuzz = 0;
1730 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001731 }
1732
1733 if (orientationChanged || sizeChanged) {
1734 // Compute oriented surface dimensions, precision, and scales.
1735 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001736 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001737 case DISPLAY_ORIENTATION_90:
1738 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001739 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1740 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1741 mLocked.orientedXPrecision = mLocked.yPrecision;
1742 mLocked.orientedYPrecision = mLocked.xPrecision;
1743 orientedXScale = mLocked.yScale;
1744 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001745 break;
1746 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001747 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1748 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1749 mLocked.orientedXPrecision = mLocked.xPrecision;
1750 mLocked.orientedYPrecision = mLocked.yPrecision;
1751 orientedXScale = mLocked.xScale;
1752 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001753 break;
1754 }
1755
1756 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001757 mLocked.orientedRanges.x.min = 0;
1758 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1759 mLocked.orientedRanges.x.flat = 0;
1760 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001761
Jeff Brown6328cdc2010-07-29 18:18:33 -07001762 mLocked.orientedRanges.y.min = 0;
1763 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1764 mLocked.orientedRanges.y.flat = 0;
1765 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001766 }
1767
1768 return true;
1769}
1770
Jeff Brownef3d7e82010-09-30 14:33:04 -07001771void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1772 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1773 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1774 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001775}
1776
Jeff Brown6328cdc2010-07-29 18:18:33 -07001777void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001778 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001779
Jeff Brown8d608662010-08-30 03:02:23 -07001780 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001781 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001782
Jeff Brown6328cdc2010-07-29 18:18:33 -07001783 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001784
Jeff Brown6328cdc2010-07-29 18:18:33 -07001785 if (virtualKeyDefinitions.size() == 0) {
1786 return;
1787 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001788
Jeff Brown6328cdc2010-07-29 18:18:33 -07001789 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1790
Jeff Brown8d608662010-08-30 03:02:23 -07001791 int32_t touchScreenLeft = mRawAxes.x.minValue;
1792 int32_t touchScreenTop = mRawAxes.y.minValue;
1793 int32_t touchScreenWidth = mRawAxes.x.getRange();
1794 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001795
1796 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001797 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001798 virtualKeyDefinitions[i];
1799
1800 mLocked.virtualKeys.add();
1801 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1802
1803 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1804 int32_t keyCode;
1805 uint32_t flags;
1806 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1807 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001808 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1809 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001810 mLocked.virtualKeys.pop(); // drop the key
1811 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001812 }
1813
Jeff Brown6328cdc2010-07-29 18:18:33 -07001814 virtualKey.keyCode = keyCode;
1815 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001816
Jeff Brown6328cdc2010-07-29 18:18:33 -07001817 // convert the key definition's display coordinates into touch coordinates for a hit box
1818 int32_t halfWidth = virtualKeyDefinition.width / 2;
1819 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001820
Jeff Brown6328cdc2010-07-29 18:18:33 -07001821 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1822 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1823 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1824 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1825 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1826 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1827 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1828 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001829
Jeff Brownef3d7e82010-09-30 14:33:04 -07001830 }
1831}
1832
1833void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1834 if (!mLocked.virtualKeys.isEmpty()) {
1835 dump.append(INDENT3 "Virtual Keys:\n");
1836
1837 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1838 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1839 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1840 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1841 i, virtualKey.scanCode, virtualKey.keyCode,
1842 virtualKey.hitLeft, virtualKey.hitRight,
1843 virtualKey.hitTop, virtualKey.hitBottom);
1844 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001845 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001846}
1847
Jeff Brown8d608662010-08-30 03:02:23 -07001848void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001849 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001850 Calibration& out = mCalibration;
1851
Jeff Brown511ee5f2010-10-18 13:32:20 -07001852 // Position
1853 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1854 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1855 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1856 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1857
Jeff Brownc6d282b2010-10-14 21:42:15 -07001858 // Touch Size
1859 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1860 String8 touchSizeCalibrationString;
1861 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1862 if (touchSizeCalibrationString == "none") {
1863 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1864 } else if (touchSizeCalibrationString == "geometric") {
1865 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1866 } else if (touchSizeCalibrationString == "pressure") {
1867 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1868 } else if (touchSizeCalibrationString != "default") {
1869 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1870 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001871 }
1872 }
1873
Jeff Brownc6d282b2010-10-14 21:42:15 -07001874 // Tool Size
1875 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1876 String8 toolSizeCalibrationString;
1877 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1878 if (toolSizeCalibrationString == "none") {
1879 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1880 } else if (toolSizeCalibrationString == "geometric") {
1881 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1882 } else if (toolSizeCalibrationString == "linear") {
1883 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1884 } else if (toolSizeCalibrationString == "area") {
1885 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1886 } else if (toolSizeCalibrationString != "default") {
1887 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1888 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001889 }
1890 }
1891
Jeff Brownc6d282b2010-10-14 21:42:15 -07001892 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1893 out.toolSizeLinearScale);
1894 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1895 out.toolSizeLinearBias);
1896 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1897 out.toolSizeAreaScale);
1898 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1899 out.toolSizeAreaBias);
1900 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1901 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07001902
1903 // Pressure
1904 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1905 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001906 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001907 if (pressureCalibrationString == "none") {
1908 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1909 } else if (pressureCalibrationString == "physical") {
1910 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1911 } else if (pressureCalibrationString == "amplitude") {
1912 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1913 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001914 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001915 pressureCalibrationString.string());
1916 }
1917 }
1918
1919 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1920 String8 pressureSourceString;
1921 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1922 if (pressureSourceString == "pressure") {
1923 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1924 } else if (pressureSourceString == "touch") {
1925 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1926 } else if (pressureSourceString != "default") {
1927 LOGW("Invalid value for touch.pressure.source: '%s'",
1928 pressureSourceString.string());
1929 }
1930 }
1931
1932 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1933 out.pressureScale);
1934
1935 // Size
1936 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1937 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001938 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001939 if (sizeCalibrationString == "none") {
1940 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1941 } else if (sizeCalibrationString == "normalized") {
1942 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1943 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001944 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001945 sizeCalibrationString.string());
1946 }
1947 }
1948
1949 // Orientation
1950 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1951 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001952 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001953 if (orientationCalibrationString == "none") {
1954 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1955 } else if (orientationCalibrationString == "interpolated") {
1956 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08001957 } else if (orientationCalibrationString == "vector") {
1958 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001959 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001960 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001961 orientationCalibrationString.string());
1962 }
1963 }
1964}
1965
1966void TouchInputMapper::resolveCalibration() {
1967 // Pressure
1968 switch (mCalibration.pressureSource) {
1969 case Calibration::PRESSURE_SOURCE_DEFAULT:
1970 if (mRawAxes.pressure.valid) {
1971 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1972 } else if (mRawAxes.touchMajor.valid) {
1973 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1974 }
1975 break;
1976
1977 case Calibration::PRESSURE_SOURCE_PRESSURE:
1978 if (! mRawAxes.pressure.valid) {
1979 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1980 "the pressure axis is not available.");
1981 }
1982 break;
1983
1984 case Calibration::PRESSURE_SOURCE_TOUCH:
1985 if (! mRawAxes.touchMajor.valid) {
1986 LOGW("Calibration property touch.pressure.source is 'touch' but "
1987 "the touchMajor axis is not available.");
1988 }
1989 break;
1990
1991 default:
1992 break;
1993 }
1994
1995 switch (mCalibration.pressureCalibration) {
1996 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1997 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1998 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1999 } else {
2000 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2001 }
2002 break;
2003
2004 default:
2005 break;
2006 }
2007
Jeff Brownc6d282b2010-10-14 21:42:15 -07002008 // Tool Size
2009 switch (mCalibration.toolSizeCalibration) {
2010 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002011 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002012 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002013 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002014 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002015 }
2016 break;
2017
2018 default:
2019 break;
2020 }
2021
Jeff Brownc6d282b2010-10-14 21:42:15 -07002022 // Touch Size
2023 switch (mCalibration.touchSizeCalibration) {
2024 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002025 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002026 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2027 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002028 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002029 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002030 }
2031 break;
2032
2033 default:
2034 break;
2035 }
2036
2037 // Size
2038 switch (mCalibration.sizeCalibration) {
2039 case Calibration::SIZE_CALIBRATION_DEFAULT:
2040 if (mRawAxes.toolMajor.valid) {
2041 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2042 } else {
2043 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2044 }
2045 break;
2046
2047 default:
2048 break;
2049 }
2050
2051 // Orientation
2052 switch (mCalibration.orientationCalibration) {
2053 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2054 if (mRawAxes.orientation.valid) {
2055 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2056 } else {
2057 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2058 }
2059 break;
2060
2061 default:
2062 break;
2063 }
2064}
2065
Jeff Brownef3d7e82010-09-30 14:33:04 -07002066void TouchInputMapper::dumpCalibration(String8& dump) {
2067 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002068
Jeff Brown511ee5f2010-10-18 13:32:20 -07002069 // Position
2070 if (mCalibration.haveXOrigin) {
2071 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2072 }
2073 if (mCalibration.haveYOrigin) {
2074 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2075 }
2076 if (mCalibration.haveXScale) {
2077 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2078 }
2079 if (mCalibration.haveYScale) {
2080 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2081 }
2082
Jeff Brownc6d282b2010-10-14 21:42:15 -07002083 // Touch Size
2084 switch (mCalibration.touchSizeCalibration) {
2085 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2086 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002087 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002088 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2089 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002090 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002091 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2092 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002093 break;
2094 default:
2095 assert(false);
2096 }
2097
Jeff Brownc6d282b2010-10-14 21:42:15 -07002098 // Tool Size
2099 switch (mCalibration.toolSizeCalibration) {
2100 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2101 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002102 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002103 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2104 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002105 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002106 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2107 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2108 break;
2109 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2110 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002111 break;
2112 default:
2113 assert(false);
2114 }
2115
Jeff Brownc6d282b2010-10-14 21:42:15 -07002116 if (mCalibration.haveToolSizeLinearScale) {
2117 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2118 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002119 }
2120
Jeff Brownc6d282b2010-10-14 21:42:15 -07002121 if (mCalibration.haveToolSizeLinearBias) {
2122 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2123 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002124 }
2125
Jeff Brownc6d282b2010-10-14 21:42:15 -07002126 if (mCalibration.haveToolSizeAreaScale) {
2127 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2128 mCalibration.toolSizeAreaScale);
2129 }
2130
2131 if (mCalibration.haveToolSizeAreaBias) {
2132 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2133 mCalibration.toolSizeAreaBias);
2134 }
2135
2136 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002137 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002138 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002139 }
2140
2141 // Pressure
2142 switch (mCalibration.pressureCalibration) {
2143 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002144 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002145 break;
2146 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002147 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002148 break;
2149 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002150 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002151 break;
2152 default:
2153 assert(false);
2154 }
2155
2156 switch (mCalibration.pressureSource) {
2157 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002158 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002159 break;
2160 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002161 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002162 break;
2163 case Calibration::PRESSURE_SOURCE_DEFAULT:
2164 break;
2165 default:
2166 assert(false);
2167 }
2168
2169 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002170 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2171 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002172 }
2173
2174 // Size
2175 switch (mCalibration.sizeCalibration) {
2176 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002177 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002178 break;
2179 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002180 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002181 break;
2182 default:
2183 assert(false);
2184 }
2185
2186 // Orientation
2187 switch (mCalibration.orientationCalibration) {
2188 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002189 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002190 break;
2191 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002192 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002193 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002194 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2195 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2196 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002197 default:
2198 assert(false);
2199 }
2200}
2201
Jeff Brown6d0fec22010-07-23 21:28:06 -07002202void TouchInputMapper::reset() {
2203 // Synthesize touch up event if touch is currently down.
2204 // This will also take care of finishing virtual key processing if needed.
2205 if (mLastTouch.pointerCount != 0) {
2206 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2207 mCurrentTouch.clear();
2208 syncTouch(when, true);
2209 }
2210
Jeff Brown6328cdc2010-07-29 18:18:33 -07002211 { // acquire lock
2212 AutoMutex _l(mLock);
2213 initializeLocked();
2214 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002215
Jeff Brown6328cdc2010-07-29 18:18:33 -07002216 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002217}
2218
2219void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002220 uint32_t policyFlags = 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002221
Jeff Brown6328cdc2010-07-29 18:18:33 -07002222 // Preprocess pointer data.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002223
Jeff Brown6d0fec22010-07-23 21:28:06 -07002224 if (mParameters.useBadTouchFilter) {
2225 if (applyBadTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002226 havePointerIds = false;
2227 }
2228 }
2229
Jeff Brown6d0fec22010-07-23 21:28:06 -07002230 if (mParameters.useJumpyTouchFilter) {
2231 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002232 havePointerIds = false;
2233 }
2234 }
2235
2236 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002237 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002238 }
2239
Jeff Brown6d0fec22010-07-23 21:28:06 -07002240 TouchData temp;
2241 TouchData* savedTouch;
2242 if (mParameters.useAveragingTouchFilter) {
2243 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002244 savedTouch = & temp;
2245
Jeff Brown6d0fec22010-07-23 21:28:06 -07002246 applyAveragingTouchFilter();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002247 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002248 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002249 }
2250
Jeff Brown6328cdc2010-07-29 18:18:33 -07002251 // Process touches and virtual keys.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002252
Jeff Brown6d0fec22010-07-23 21:28:06 -07002253 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2254 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002255 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002256 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002257 }
2258
Jeff Brown6328cdc2010-07-29 18:18:33 -07002259 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002260
Jeff Brown6d0fec22010-07-23 21:28:06 -07002261 if (touchResult == DROP_STROKE) {
2262 mLastTouch.clear();
2263 } else {
2264 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002265 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002266}
2267
Jeff Brown6d0fec22010-07-23 21:28:06 -07002268TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2269 nsecs_t when, uint32_t policyFlags) {
2270 int32_t keyEventAction, keyEventFlags;
2271 int32_t keyCode, scanCode, downTime;
2272 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002273
Jeff Brown6328cdc2010-07-29 18:18:33 -07002274 { // acquire lock
2275 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002276
Jeff Brown6328cdc2010-07-29 18:18:33 -07002277 // Update surface size and orientation, including virtual key positions.
2278 if (! configureSurfaceLocked()) {
2279 return DROP_STROKE;
2280 }
2281
2282 // Check for virtual key press.
2283 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002284 if (mCurrentTouch.pointerCount == 0) {
2285 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002286 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002287#if DEBUG_VIRTUAL_KEYS
2288 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002289 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002290#endif
2291 keyEventAction = AKEY_EVENT_ACTION_UP;
2292 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2293 touchResult = SKIP_TOUCH;
2294 goto DispatchVirtualKey;
2295 }
2296
2297 if (mCurrentTouch.pointerCount == 1) {
2298 int32_t x = mCurrentTouch.pointers[0].x;
2299 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002300 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2301 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002302 // Pointer is still within the space of the virtual key.
2303 return SKIP_TOUCH;
2304 }
2305 }
2306
2307 // Pointer left virtual key area or another pointer also went down.
2308 // Send key cancellation and drop the stroke so subsequent motions will be
2309 // considered fresh downs. This is useful when the user swipes away from the
2310 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002311 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002312#if DEBUG_VIRTUAL_KEYS
2313 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002314 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002315#endif
2316 keyEventAction = AKEY_EVENT_ACTION_UP;
2317 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2318 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002319
2320 // Check whether the pointer moved inside the display area where we should
2321 // start a new stroke.
2322 int32_t x = mCurrentTouch.pointers[0].x;
2323 int32_t y = mCurrentTouch.pointers[0].y;
2324 if (isPointInsideSurfaceLocked(x, y)) {
2325 mLastTouch.clear();
2326 touchResult = DISPATCH_TOUCH;
2327 } else {
2328 touchResult = DROP_STROKE;
2329 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002330 } else {
2331 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2332 // Pointer just went down. Handle off-screen touches, if needed.
2333 int32_t x = mCurrentTouch.pointers[0].x;
2334 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002335 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002336 // If exactly one pointer went down, check for virtual key hit.
2337 // Otherwise we will drop the entire stroke.
2338 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002339 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002340 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002341 if (mContext->shouldDropVirtualKey(when, getDevice(),
2342 virtualKey->keyCode, virtualKey->scanCode)) {
2343 return DROP_STROKE;
2344 }
2345
Jeff Brown6328cdc2010-07-29 18:18:33 -07002346 mLocked.currentVirtualKey.down = true;
2347 mLocked.currentVirtualKey.downTime = when;
2348 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2349 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002350#if DEBUG_VIRTUAL_KEYS
2351 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002352 mLocked.currentVirtualKey.keyCode,
2353 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002354#endif
2355 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2356 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2357 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2358 touchResult = SKIP_TOUCH;
2359 goto DispatchVirtualKey;
2360 }
2361 }
2362 return DROP_STROKE;
2363 }
2364 }
2365 return DISPATCH_TOUCH;
2366 }
2367
2368 DispatchVirtualKey:
2369 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002370 keyCode = mLocked.currentVirtualKey.keyCode;
2371 scanCode = mLocked.currentVirtualKey.scanCode;
2372 downTime = mLocked.currentVirtualKey.downTime;
2373 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002374
2375 // Dispatch virtual key.
2376 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002377 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002378 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2379 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2380 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002381}
2382
Jeff Brownfe508922011-01-18 15:10:10 -08002383void TouchInputMapper::detectGestures(nsecs_t when) {
2384 // Disable all virtual key touches that happen within a short time interval of the
2385 // most recent touch. The idea is to filter out stray virtual key presses when
2386 // interacting with the touch screen.
2387 //
2388 // Problems we're trying to solve:
2389 //
2390 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2391 // virtual key area that is implemented by a separate touch panel and accidentally
2392 // triggers a virtual key.
2393 //
2394 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2395 // area and accidentally triggers a virtual key. This often happens when virtual keys
2396 // are layed out below the screen near to where the on screen keyboard's space bar
2397 // is displayed.
2398 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2399 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2400 }
2401}
2402
Jeff Brown6d0fec22010-07-23 21:28:06 -07002403void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2404 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2405 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002406 if (currentPointerCount == 0 && lastPointerCount == 0) {
2407 return; // nothing to do!
2408 }
2409
Jeff Brown6d0fec22010-07-23 21:28:06 -07002410 BitSet32 currentIdBits = mCurrentTouch.idBits;
2411 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002412
2413 if (currentIdBits == lastIdBits) {
2414 // No pointer id changes so this is a move event.
2415 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002416 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002417 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002418 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002419 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002420 // There may be pointers going up and pointers going down and pointers moving
2421 // all at the same time.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002422 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2423 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2424 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002425 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002426
Jeff Brownc3db8582010-10-20 15:33:38 -07002427 // Produce an intermediate representation of the touch data that consists of the
2428 // old location of pointers that have just gone up and the new location of pointers that
2429 // have just moved but omits the location of pointers that have just gone down.
2430 TouchData interimTouch;
2431 interimTouch.copyFrom(mLastTouch);
2432
2433 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2434 bool moveNeeded = false;
2435 while (!moveIdBits.isEmpty()) {
2436 uint32_t moveId = moveIdBits.firstMarkedBit();
2437 moveIdBits.clearBit(moveId);
2438
2439 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2440 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2441 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2442 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2443 moveNeeded = true;
2444 }
2445 }
2446
2447 // Dispatch pointer up events using the interim pointer locations.
2448 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002449 uint32_t upId = upIdBits.firstMarkedBit();
2450 upIdBits.clearBit(upId);
2451 BitSet32 oldActiveIdBits = activeIdBits;
2452 activeIdBits.clearBit(upId);
2453
2454 int32_t motionEventAction;
2455 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002456 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002457 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002458 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002459 }
2460
Jeff Brownc3db8582010-10-20 15:33:38 -07002461 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002462 oldActiveIdBits, upId, pointerCount, motionEventAction);
2463 pointerCount -= 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002464 }
2465
Jeff Brownc3db8582010-10-20 15:33:38 -07002466 // Dispatch move events if any of the remaining pointers moved from their old locations.
2467 // Although applications receive new locations as part of individual pointer up
2468 // events, they do not generally handle them except when presented in a move event.
2469 if (moveNeeded) {
2470 dispatchTouch(when, policyFlags, &mCurrentTouch,
2471 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2472 }
2473
2474 // Dispatch pointer down events using the new pointer locations.
2475 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002476 uint32_t downId = downIdBits.firstMarkedBit();
2477 downIdBits.clearBit(downId);
2478 BitSet32 oldActiveIdBits = activeIdBits;
2479 activeIdBits.markBit(downId);
2480
2481 int32_t motionEventAction;
2482 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002483 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002484 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002485 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002486 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002487 }
2488
Jeff Brown8d608662010-08-30 03:02:23 -07002489 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002490 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002491 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002492 }
2493 }
2494}
2495
Jeff Brown6d0fec22010-07-23 21:28:06 -07002496void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002497 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002498 int32_t motionEventAction) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002499 int32_t pointerIds[MAX_POINTERS];
2500 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002501 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002502 float xPrecision, yPrecision;
2503
2504 { // acquire lock
2505 AutoMutex _l(mLock);
2506
2507 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2508 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002509 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002510 uint32_t id = idBits.firstMarkedBit();
2511 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002512 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002513
Jeff Brown8d608662010-08-30 03:02:23 -07002514 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002515
Jeff Brown8d608662010-08-30 03:02:23 -07002516 // X and Y
2517 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2518 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002519
Jeff Brown8d608662010-08-30 03:02:23 -07002520 // ToolMajor and ToolMinor
2521 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002522 switch (mCalibration.toolSizeCalibration) {
2523 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002524 toolMajor = in.toolMajor * mLocked.geometricScale;
2525 if (mRawAxes.toolMinor.valid) {
2526 toolMinor = in.toolMinor * mLocked.geometricScale;
2527 } else {
2528 toolMinor = toolMajor;
2529 }
2530 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002531 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002532 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002533 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002534 : 0;
2535 if (mRawAxes.toolMinor.valid) {
2536 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002537 ? in.toolMinor * mLocked.toolSizeLinearScale
2538 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002539 : 0;
2540 } else {
2541 toolMinor = toolMajor;
2542 }
2543 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002544 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2545 if (in.toolMajor != 0) {
2546 float diameter = sqrtf(in.toolMajor
2547 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2548 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2549 } else {
2550 toolMajor = 0;
2551 }
2552 toolMinor = toolMajor;
2553 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002554 default:
2555 toolMajor = 0;
2556 toolMinor = 0;
2557 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002558 }
2559
Jeff Brownc6d282b2010-10-14 21:42:15 -07002560 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002561 toolMajor /= pointerCount;
2562 toolMinor /= pointerCount;
2563 }
2564
2565 // Pressure
2566 float rawPressure;
2567 switch (mCalibration.pressureSource) {
2568 case Calibration::PRESSURE_SOURCE_PRESSURE:
2569 rawPressure = in.pressure;
2570 break;
2571 case Calibration::PRESSURE_SOURCE_TOUCH:
2572 rawPressure = in.touchMajor;
2573 break;
2574 default:
2575 rawPressure = 0;
2576 }
2577
2578 float pressure;
2579 switch (mCalibration.pressureCalibration) {
2580 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2581 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2582 pressure = rawPressure * mLocked.pressureScale;
2583 break;
2584 default:
2585 pressure = 1;
2586 break;
2587 }
2588
2589 // TouchMajor and TouchMinor
2590 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002591 switch (mCalibration.touchSizeCalibration) {
2592 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002593 touchMajor = in.touchMajor * mLocked.geometricScale;
2594 if (mRawAxes.touchMinor.valid) {
2595 touchMinor = in.touchMinor * mLocked.geometricScale;
2596 } else {
2597 touchMinor = touchMajor;
2598 }
2599 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002600 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002601 touchMajor = toolMajor * pressure;
2602 touchMinor = toolMinor * pressure;
2603 break;
2604 default:
2605 touchMajor = 0;
2606 touchMinor = 0;
2607 break;
2608 }
2609
2610 if (touchMajor > toolMajor) {
2611 touchMajor = toolMajor;
2612 }
2613 if (touchMinor > toolMinor) {
2614 touchMinor = toolMinor;
2615 }
2616
2617 // Size
2618 float size;
2619 switch (mCalibration.sizeCalibration) {
2620 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2621 float rawSize = mRawAxes.toolMinor.valid
2622 ? avg(in.toolMajor, in.toolMinor)
2623 : in.toolMajor;
2624 size = rawSize * mLocked.sizeScale;
2625 break;
2626 }
2627 default:
2628 size = 0;
2629 break;
2630 }
2631
2632 // Orientation
2633 float orientation;
2634 switch (mCalibration.orientationCalibration) {
2635 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2636 orientation = in.orientation * mLocked.orientationScale;
2637 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002638 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2639 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2640 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2641 if (c1 != 0 || c2 != 0) {
2642 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002643 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2644 touchMajor *= scale;
2645 touchMinor /= scale;
2646 toolMajor *= scale;
2647 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002648 } else {
2649 orientation = 0;
2650 }
2651 break;
2652 }
Jeff Brown8d608662010-08-30 03:02:23 -07002653 default:
2654 orientation = 0;
2655 }
2656
2657 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002658 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002659 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002660 float xTemp = x;
2661 x = y;
2662 y = mLocked.surfaceWidth - xTemp;
2663 orientation -= M_PI_2;
2664 if (orientation < - M_PI_2) {
2665 orientation += M_PI;
2666 }
2667 break;
2668 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002669 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002670 x = mLocked.surfaceWidth - x;
2671 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002672 break;
2673 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002674 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002675 float xTemp = x;
2676 x = mLocked.surfaceHeight - y;
2677 y = xTemp;
2678 orientation += M_PI_2;
2679 if (orientation > M_PI_2) {
2680 orientation -= M_PI;
2681 }
2682 break;
2683 }
2684 }
2685
Jeff Brown8d608662010-08-30 03:02:23 -07002686 // Write output coords.
2687 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002688 out.clear();
2689 out.setAxisValue(AINPUT_MOTION_AXIS_X, x);
2690 out.setAxisValue(AINPUT_MOTION_AXIS_Y, y);
2691 out.setAxisValue(AINPUT_MOTION_AXIS_PRESSURE, pressure);
2692 out.setAxisValue(AINPUT_MOTION_AXIS_SIZE, size);
2693 out.setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MAJOR, touchMajor);
2694 out.setAxisValue(AINPUT_MOTION_AXIS_TOUCH_MINOR, touchMinor);
2695 out.setAxisValue(AINPUT_MOTION_AXIS_TOOL_MAJOR, toolMajor);
2696 out.setAxisValue(AINPUT_MOTION_AXIS_TOOL_MINOR, toolMinor);
2697 out.setAxisValue(AINPUT_MOTION_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002698
Jeff Brown8d608662010-08-30 03:02:23 -07002699 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002700
2701 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002702 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002703 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002704 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002705
2706 // Check edge flags by looking only at the first pointer since the flags are
2707 // global to the event.
2708 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown91c69ab2011-02-14 17:03:18 -08002709 float x = pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_X);
2710 float y = pointerCoords[0].getAxisValue(AINPUT_MOTION_AXIS_Y);
2711
2712 if (x <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002713 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002714 } else if (x >= mLocked.orientedSurfaceWidth) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002715 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2716 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08002717 if (y <= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002718 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown91c69ab2011-02-14 17:03:18 -08002719 } else if (y >= mLocked.orientedSurfaceHeight) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002720 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2721 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002722 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002723
2724 xPrecision = mLocked.orientedXPrecision;
2725 yPrecision = mLocked.orientedYPrecision;
2726 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002727
Jeff Brown83c09682010-12-23 17:50:18 -08002728 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002729 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002730 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002731 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002732}
2733
Jeff Brown6328cdc2010-07-29 18:18:33 -07002734bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002735 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2736 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2737 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002738 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002739 return true;
2740}
2741
Jeff Brown6328cdc2010-07-29 18:18:33 -07002742const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2743 int32_t x, int32_t y) {
2744 size_t numVirtualKeys = mLocked.virtualKeys.size();
2745 for (size_t i = 0; i < numVirtualKeys; i++) {
2746 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002747
2748#if DEBUG_VIRTUAL_KEYS
2749 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2750 "left=%d, top=%d, right=%d, bottom=%d",
2751 x, y,
2752 virtualKey.keyCode, virtualKey.scanCode,
2753 virtualKey.hitLeft, virtualKey.hitTop,
2754 virtualKey.hitRight, virtualKey.hitBottom);
2755#endif
2756
2757 if (virtualKey.isHit(x, y)) {
2758 return & virtualKey;
2759 }
2760 }
2761
2762 return NULL;
2763}
2764
2765void TouchInputMapper::calculatePointerIds() {
2766 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2767 uint32_t lastPointerCount = mLastTouch.pointerCount;
2768
2769 if (currentPointerCount == 0) {
2770 // No pointers to assign.
2771 mCurrentTouch.idBits.clear();
2772 } else if (lastPointerCount == 0) {
2773 // All pointers are new.
2774 mCurrentTouch.idBits.clear();
2775 for (uint32_t i = 0; i < currentPointerCount; i++) {
2776 mCurrentTouch.pointers[i].id = i;
2777 mCurrentTouch.idToIndex[i] = i;
2778 mCurrentTouch.idBits.markBit(i);
2779 }
2780 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2781 // Only one pointer and no change in count so it must have the same id as before.
2782 uint32_t id = mLastTouch.pointers[0].id;
2783 mCurrentTouch.pointers[0].id = id;
2784 mCurrentTouch.idToIndex[id] = 0;
2785 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2786 } else {
2787 // General case.
2788 // We build a heap of squared euclidean distances between current and last pointers
2789 // associated with the current and last pointer indices. Then, we find the best
2790 // match (by distance) for each current pointer.
2791 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2792
2793 uint32_t heapSize = 0;
2794 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2795 currentPointerIndex++) {
2796 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2797 lastPointerIndex++) {
2798 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2799 - mLastTouch.pointers[lastPointerIndex].x;
2800 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2801 - mLastTouch.pointers[lastPointerIndex].y;
2802
2803 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2804
2805 // Insert new element into the heap (sift up).
2806 heap[heapSize].currentPointerIndex = currentPointerIndex;
2807 heap[heapSize].lastPointerIndex = lastPointerIndex;
2808 heap[heapSize].distance = distance;
2809 heapSize += 1;
2810 }
2811 }
2812
2813 // Heapify
2814 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2815 startIndex -= 1;
2816 for (uint32_t parentIndex = startIndex; ;) {
2817 uint32_t childIndex = parentIndex * 2 + 1;
2818 if (childIndex >= heapSize) {
2819 break;
2820 }
2821
2822 if (childIndex + 1 < heapSize
2823 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2824 childIndex += 1;
2825 }
2826
2827 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2828 break;
2829 }
2830
2831 swap(heap[parentIndex], heap[childIndex]);
2832 parentIndex = childIndex;
2833 }
2834 }
2835
2836#if DEBUG_POINTER_ASSIGNMENT
2837 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2838 for (size_t i = 0; i < heapSize; i++) {
2839 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2840 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2841 heap[i].distance);
2842 }
2843#endif
2844
2845 // Pull matches out by increasing order of distance.
2846 // To avoid reassigning pointers that have already been matched, the loop keeps track
2847 // of which last and current pointers have been matched using the matchedXXXBits variables.
2848 // It also tracks the used pointer id bits.
2849 BitSet32 matchedLastBits(0);
2850 BitSet32 matchedCurrentBits(0);
2851 BitSet32 usedIdBits(0);
2852 bool first = true;
2853 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2854 for (;;) {
2855 if (first) {
2856 // The first time through the loop, we just consume the root element of
2857 // the heap (the one with smallest distance).
2858 first = false;
2859 } else {
2860 // Previous iterations consumed the root element of the heap.
2861 // Pop root element off of the heap (sift down).
2862 heapSize -= 1;
2863 assert(heapSize > 0);
2864
2865 // Sift down.
2866 heap[0] = heap[heapSize];
2867 for (uint32_t parentIndex = 0; ;) {
2868 uint32_t childIndex = parentIndex * 2 + 1;
2869 if (childIndex >= heapSize) {
2870 break;
2871 }
2872
2873 if (childIndex + 1 < heapSize
2874 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2875 childIndex += 1;
2876 }
2877
2878 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2879 break;
2880 }
2881
2882 swap(heap[parentIndex], heap[childIndex]);
2883 parentIndex = childIndex;
2884 }
2885
2886#if DEBUG_POINTER_ASSIGNMENT
2887 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2888 for (size_t i = 0; i < heapSize; i++) {
2889 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2890 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2891 heap[i].distance);
2892 }
2893#endif
2894 }
2895
2896 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2897 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2898
2899 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2900 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2901
2902 matchedCurrentBits.markBit(currentPointerIndex);
2903 matchedLastBits.markBit(lastPointerIndex);
2904
2905 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2906 mCurrentTouch.pointers[currentPointerIndex].id = id;
2907 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2908 usedIdBits.markBit(id);
2909
2910#if DEBUG_POINTER_ASSIGNMENT
2911 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2912 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2913#endif
2914 break;
2915 }
2916 }
2917
2918 // Assign fresh ids to new pointers.
2919 if (currentPointerCount > lastPointerCount) {
2920 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2921 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2922 uint32_t id = usedIdBits.firstUnmarkedBit();
2923
2924 mCurrentTouch.pointers[currentPointerIndex].id = id;
2925 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2926 usedIdBits.markBit(id);
2927
2928#if DEBUG_POINTER_ASSIGNMENT
2929 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2930 currentPointerIndex, id);
2931#endif
2932
2933 if (--i == 0) break; // done
2934 matchedCurrentBits.markBit(currentPointerIndex);
2935 }
2936 }
2937
2938 // Fix id bits.
2939 mCurrentTouch.idBits = usedIdBits;
2940 }
2941}
2942
2943/* Special hack for devices that have bad screen data: if one of the
2944 * points has moved more than a screen height from the last position,
2945 * then drop it. */
2946bool TouchInputMapper::applyBadTouchFilter() {
2947 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002948 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002949 return false;
2950 }
2951
2952 uint32_t pointerCount = mCurrentTouch.pointerCount;
2953
2954 // Nothing to do if there are no points.
2955 if (pointerCount == 0) {
2956 return false;
2957 }
2958
2959 // Don't do anything if a finger is going down or up. We run
2960 // here before assigning pointer IDs, so there isn't a good
2961 // way to do per-finger matching.
2962 if (pointerCount != mLastTouch.pointerCount) {
2963 return false;
2964 }
2965
2966 // We consider a single movement across more than a 7/16 of
2967 // the long size of the screen to be bad. This was a magic value
2968 // determined by looking at the maximum distance it is feasible
2969 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07002970 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002971
2972 // XXX The original code in InputDevice.java included commented out
2973 // code for testing the X axis. Note that when we drop a point
2974 // we don't actually restore the old X either. Strange.
2975 // The old code also tries to track when bad points were previously
2976 // detected but it turns out that due to the placement of a "break"
2977 // at the end of the loop, we never set mDroppedBadPoint to true
2978 // so it is effectively dead code.
2979 // Need to figure out if the old code is busted or just overcomplicated
2980 // but working as intended.
2981
2982 // Look through all new points and see if any are farther than
2983 // acceptable from all previous points.
2984 for (uint32_t i = pointerCount; i-- > 0; ) {
2985 int32_t y = mCurrentTouch.pointers[i].y;
2986 int32_t closestY = INT_MAX;
2987 int32_t closestDeltaY = 0;
2988
2989#if DEBUG_HACKS
2990 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2991#endif
2992
2993 for (uint32_t j = pointerCount; j-- > 0; ) {
2994 int32_t lastY = mLastTouch.pointers[j].y;
2995 int32_t deltaY = abs(y - lastY);
2996
2997#if DEBUG_HACKS
2998 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2999 j, lastY, deltaY);
3000#endif
3001
3002 if (deltaY < maxDeltaY) {
3003 goto SkipSufficientlyClosePoint;
3004 }
3005 if (deltaY < closestDeltaY) {
3006 closestDeltaY = deltaY;
3007 closestY = lastY;
3008 }
3009 }
3010
3011 // Must not have found a close enough match.
3012#if DEBUG_HACKS
3013 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3014 i, y, closestY, closestDeltaY, maxDeltaY);
3015#endif
3016
3017 mCurrentTouch.pointers[i].y = closestY;
3018 return true; // XXX original code only corrects one point
3019
3020 SkipSufficientlyClosePoint: ;
3021 }
3022
3023 // No change.
3024 return false;
3025}
3026
3027/* Special hack for devices that have bad screen data: drop points where
3028 * the coordinate value for one axis has jumped to the other pointer's location.
3029 */
3030bool TouchInputMapper::applyJumpyTouchFilter() {
3031 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07003032 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003033 return false;
3034 }
3035
3036 uint32_t pointerCount = mCurrentTouch.pointerCount;
3037 if (mLastTouch.pointerCount != pointerCount) {
3038#if DEBUG_HACKS
3039 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3040 mLastTouch.pointerCount, pointerCount);
3041 for (uint32_t i = 0; i < pointerCount; i++) {
3042 LOGD(" Pointer %d (%d, %d)", i,
3043 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3044 }
3045#endif
3046
3047 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3048 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3049 // Just drop the first few events going from 1 to 2 pointers.
3050 // They're bad often enough that they're not worth considering.
3051 mCurrentTouch.pointerCount = 1;
3052 mJumpyTouchFilter.jumpyPointsDropped += 1;
3053
3054#if DEBUG_HACKS
3055 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3056#endif
3057 return true;
3058 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3059 // The event when we go from 2 -> 1 tends to be messed up too
3060 mCurrentTouch.pointerCount = 2;
3061 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3062 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3063 mJumpyTouchFilter.jumpyPointsDropped += 1;
3064
3065#if DEBUG_HACKS
3066 for (int32_t i = 0; i < 2; i++) {
3067 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3068 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3069 }
3070#endif
3071 return true;
3072 }
3073 }
3074 // Reset jumpy points dropped on other transitions or if limit exceeded.
3075 mJumpyTouchFilter.jumpyPointsDropped = 0;
3076
3077#if DEBUG_HACKS
3078 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3079#endif
3080 return false;
3081 }
3082
3083 // We have the same number of pointers as last time.
3084 // A 'jumpy' point is one where the coordinate value for one axis
3085 // has jumped to the other pointer's location. No need to do anything
3086 // else if we only have one pointer.
3087 if (pointerCount < 2) {
3088 return false;
3089 }
3090
3091 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003092 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003093
3094 // We only replace the single worst jumpy point as characterized by pointer distance
3095 // in a single axis.
3096 int32_t badPointerIndex = -1;
3097 int32_t badPointerReplacementIndex = -1;
3098 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3099
3100 for (uint32_t i = pointerCount; i-- > 0; ) {
3101 int32_t x = mCurrentTouch.pointers[i].x;
3102 int32_t y = mCurrentTouch.pointers[i].y;
3103
3104#if DEBUG_HACKS
3105 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3106#endif
3107
3108 // Check if a touch point is too close to another's coordinates
3109 bool dropX = false, dropY = false;
3110 for (uint32_t j = 0; j < pointerCount; j++) {
3111 if (i == j) {
3112 continue;
3113 }
3114
3115 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3116 dropX = true;
3117 break;
3118 }
3119
3120 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3121 dropY = true;
3122 break;
3123 }
3124 }
3125 if (! dropX && ! dropY) {
3126 continue; // not jumpy
3127 }
3128
3129 // Find a replacement candidate by comparing with older points on the
3130 // complementary (non-jumpy) axis.
3131 int32_t distance = INT_MIN; // distance to be corrected
3132 int32_t replacementIndex = -1;
3133
3134 if (dropX) {
3135 // X looks too close. Find an older replacement point with a close Y.
3136 int32_t smallestDeltaY = INT_MAX;
3137 for (uint32_t j = 0; j < pointerCount; j++) {
3138 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3139 if (deltaY < smallestDeltaY) {
3140 smallestDeltaY = deltaY;
3141 replacementIndex = j;
3142 }
3143 }
3144 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3145 } else {
3146 // Y looks too close. Find an older replacement point with a close X.
3147 int32_t smallestDeltaX = INT_MAX;
3148 for (uint32_t j = 0; j < pointerCount; j++) {
3149 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3150 if (deltaX < smallestDeltaX) {
3151 smallestDeltaX = deltaX;
3152 replacementIndex = j;
3153 }
3154 }
3155 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3156 }
3157
3158 // If replacing this pointer would correct a worse error than the previous ones
3159 // considered, then use this replacement instead.
3160 if (distance > badPointerDistance) {
3161 badPointerIndex = i;
3162 badPointerReplacementIndex = replacementIndex;
3163 badPointerDistance = distance;
3164 }
3165 }
3166
3167 // Correct the jumpy pointer if one was found.
3168 if (badPointerIndex >= 0) {
3169#if DEBUG_HACKS
3170 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3171 badPointerIndex,
3172 mLastTouch.pointers[badPointerReplacementIndex].x,
3173 mLastTouch.pointers[badPointerReplacementIndex].y);
3174#endif
3175
3176 mCurrentTouch.pointers[badPointerIndex].x =
3177 mLastTouch.pointers[badPointerReplacementIndex].x;
3178 mCurrentTouch.pointers[badPointerIndex].y =
3179 mLastTouch.pointers[badPointerReplacementIndex].y;
3180 mJumpyTouchFilter.jumpyPointsDropped += 1;
3181 return true;
3182 }
3183 }
3184
3185 mJumpyTouchFilter.jumpyPointsDropped = 0;
3186 return false;
3187}
3188
3189/* Special hack for devices that have bad screen data: aggregate and
3190 * compute averages of the coordinate data, to reduce the amount of
3191 * jitter seen by applications. */
3192void TouchInputMapper::applyAveragingTouchFilter() {
3193 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3194 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3195 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3196 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003197 int32_t pressure;
3198 switch (mCalibration.pressureSource) {
3199 case Calibration::PRESSURE_SOURCE_PRESSURE:
3200 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3201 break;
3202 case Calibration::PRESSURE_SOURCE_TOUCH:
3203 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3204 break;
3205 default:
3206 pressure = 1;
3207 break;
3208 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003209
3210 if (mLastTouch.idBits.hasBit(id)) {
3211 // Pointer was down before and is still down now.
3212 // Compute average over history trace.
3213 uint32_t start = mAveragingTouchFilter.historyStart[id];
3214 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3215
3216 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3217 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3218 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3219
3220#if DEBUG_HACKS
3221 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3222 id, distance);
3223#endif
3224
3225 if (distance < AVERAGING_DISTANCE_LIMIT) {
3226 // Increment end index in preparation for recording new historical data.
3227 end += 1;
3228 if (end > AVERAGING_HISTORY_SIZE) {
3229 end = 0;
3230 }
3231
3232 // If the end index has looped back to the start index then we have filled
3233 // the historical trace up to the desired size so we drop the historical
3234 // data at the start of the trace.
3235 if (end == start) {
3236 start += 1;
3237 if (start > AVERAGING_HISTORY_SIZE) {
3238 start = 0;
3239 }
3240 }
3241
3242 // Add the raw data to the historical trace.
3243 mAveragingTouchFilter.historyStart[id] = start;
3244 mAveragingTouchFilter.historyEnd[id] = end;
3245 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3246 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3247 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3248
3249 // Average over all historical positions in the trace by total pressure.
3250 int32_t averagedX = 0;
3251 int32_t averagedY = 0;
3252 int32_t totalPressure = 0;
3253 for (;;) {
3254 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3255 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3256 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3257 .pointers[id].pressure;
3258
3259 averagedX += historicalX * historicalPressure;
3260 averagedY += historicalY * historicalPressure;
3261 totalPressure += historicalPressure;
3262
3263 if (start == end) {
3264 break;
3265 }
3266
3267 start += 1;
3268 if (start > AVERAGING_HISTORY_SIZE) {
3269 start = 0;
3270 }
3271 }
3272
Jeff Brown8d608662010-08-30 03:02:23 -07003273 if (totalPressure != 0) {
3274 averagedX /= totalPressure;
3275 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003276
3277#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003278 LOGD("AveragingTouchFilter: Pointer id %d - "
3279 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3280 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003281#endif
3282
Jeff Brown8d608662010-08-30 03:02:23 -07003283 mCurrentTouch.pointers[currentIndex].x = averagedX;
3284 mCurrentTouch.pointers[currentIndex].y = averagedY;
3285 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003286 } else {
3287#if DEBUG_HACKS
3288 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3289#endif
3290 }
3291 } else {
3292#if DEBUG_HACKS
3293 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3294#endif
3295 }
3296
3297 // Reset pointer history.
3298 mAveragingTouchFilter.historyStart[id] = 0;
3299 mAveragingTouchFilter.historyEnd[id] = 0;
3300 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3301 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3302 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3303 }
3304}
3305
3306int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003307 { // acquire lock
3308 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003309
Jeff Brown6328cdc2010-07-29 18:18:33 -07003310 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003311 return AKEY_STATE_VIRTUAL;
3312 }
3313
Jeff Brown6328cdc2010-07-29 18:18:33 -07003314 size_t numVirtualKeys = mLocked.virtualKeys.size();
3315 for (size_t i = 0; i < numVirtualKeys; i++) {
3316 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003317 if (virtualKey.keyCode == keyCode) {
3318 return AKEY_STATE_UP;
3319 }
3320 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003321 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003322
3323 return AKEY_STATE_UNKNOWN;
3324}
3325
3326int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003327 { // acquire lock
3328 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003329
Jeff Brown6328cdc2010-07-29 18:18:33 -07003330 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003331 return AKEY_STATE_VIRTUAL;
3332 }
3333
Jeff Brown6328cdc2010-07-29 18:18:33 -07003334 size_t numVirtualKeys = mLocked.virtualKeys.size();
3335 for (size_t i = 0; i < numVirtualKeys; i++) {
3336 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003337 if (virtualKey.scanCode == scanCode) {
3338 return AKEY_STATE_UP;
3339 }
3340 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003341 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003342
3343 return AKEY_STATE_UNKNOWN;
3344}
3345
3346bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3347 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003348 { // acquire lock
3349 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003350
Jeff Brown6328cdc2010-07-29 18:18:33 -07003351 size_t numVirtualKeys = mLocked.virtualKeys.size();
3352 for (size_t i = 0; i < numVirtualKeys; i++) {
3353 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003354
3355 for (size_t i = 0; i < numCodes; i++) {
3356 if (virtualKey.keyCode == keyCodes[i]) {
3357 outFlags[i] = 1;
3358 }
3359 }
3360 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003361 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003362
3363 return true;
3364}
3365
3366
3367// --- SingleTouchInputMapper ---
3368
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003369SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3370 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003371 initialize();
3372}
3373
3374SingleTouchInputMapper::~SingleTouchInputMapper() {
3375}
3376
3377void SingleTouchInputMapper::initialize() {
3378 mAccumulator.clear();
3379
3380 mDown = false;
3381 mX = 0;
3382 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003383 mPressure = 0; // default to 0 for devices that don't report pressure
3384 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003385}
3386
3387void SingleTouchInputMapper::reset() {
3388 TouchInputMapper::reset();
3389
Jeff Brown6d0fec22010-07-23 21:28:06 -07003390 initialize();
3391 }
3392
3393void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3394 switch (rawEvent->type) {
3395 case EV_KEY:
3396 switch (rawEvent->scanCode) {
3397 case BTN_TOUCH:
3398 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3399 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003400 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3401 // not have received valid position information yet. This logic assumes that
3402 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003403 break;
3404 }
3405 break;
3406
3407 case EV_ABS:
3408 switch (rawEvent->scanCode) {
3409 case ABS_X:
3410 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3411 mAccumulator.absX = rawEvent->value;
3412 break;
3413 case ABS_Y:
3414 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3415 mAccumulator.absY = rawEvent->value;
3416 break;
3417 case ABS_PRESSURE:
3418 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3419 mAccumulator.absPressure = rawEvent->value;
3420 break;
3421 case ABS_TOOL_WIDTH:
3422 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3423 mAccumulator.absToolWidth = rawEvent->value;
3424 break;
3425 }
3426 break;
3427
3428 case EV_SYN:
3429 switch (rawEvent->scanCode) {
3430 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003431 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003432 break;
3433 }
3434 break;
3435 }
3436}
3437
3438void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003439 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003440 if (fields == 0) {
3441 return; // no new state changes, so nothing to do
3442 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003443
3444 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3445 mDown = mAccumulator.btnTouch;
3446 }
3447
3448 if (fields & Accumulator::FIELD_ABS_X) {
3449 mX = mAccumulator.absX;
3450 }
3451
3452 if (fields & Accumulator::FIELD_ABS_Y) {
3453 mY = mAccumulator.absY;
3454 }
3455
3456 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3457 mPressure = mAccumulator.absPressure;
3458 }
3459
3460 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003461 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003462 }
3463
3464 mCurrentTouch.clear();
3465
3466 if (mDown) {
3467 mCurrentTouch.pointerCount = 1;
3468 mCurrentTouch.pointers[0].id = 0;
3469 mCurrentTouch.pointers[0].x = mX;
3470 mCurrentTouch.pointers[0].y = mY;
3471 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003472 mCurrentTouch.pointers[0].touchMajor = 0;
3473 mCurrentTouch.pointers[0].touchMinor = 0;
3474 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3475 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003476 mCurrentTouch.pointers[0].orientation = 0;
3477 mCurrentTouch.idToIndex[0] = 0;
3478 mCurrentTouch.idBits.markBit(0);
3479 }
3480
3481 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003482
3483 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003484}
3485
Jeff Brown8d608662010-08-30 03:02:23 -07003486void SingleTouchInputMapper::configureRawAxes() {
3487 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003488
Jeff Brown8d608662010-08-30 03:02:23 -07003489 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3490 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3491 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3492 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003493}
3494
3495
3496// --- MultiTouchInputMapper ---
3497
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003498MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3499 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003500 initialize();
3501}
3502
3503MultiTouchInputMapper::~MultiTouchInputMapper() {
3504}
3505
3506void MultiTouchInputMapper::initialize() {
3507 mAccumulator.clear();
3508}
3509
3510void MultiTouchInputMapper::reset() {
3511 TouchInputMapper::reset();
3512
Jeff Brown6d0fec22010-07-23 21:28:06 -07003513 initialize();
3514}
3515
3516void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3517 switch (rawEvent->type) {
3518 case EV_ABS: {
3519 uint32_t pointerIndex = mAccumulator.pointerCount;
3520 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3521
3522 switch (rawEvent->scanCode) {
3523 case ABS_MT_POSITION_X:
3524 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3525 pointer->absMTPositionX = rawEvent->value;
3526 break;
3527 case ABS_MT_POSITION_Y:
3528 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3529 pointer->absMTPositionY = rawEvent->value;
3530 break;
3531 case ABS_MT_TOUCH_MAJOR:
3532 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3533 pointer->absMTTouchMajor = rawEvent->value;
3534 break;
3535 case ABS_MT_TOUCH_MINOR:
3536 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3537 pointer->absMTTouchMinor = rawEvent->value;
3538 break;
3539 case ABS_MT_WIDTH_MAJOR:
3540 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3541 pointer->absMTWidthMajor = rawEvent->value;
3542 break;
3543 case ABS_MT_WIDTH_MINOR:
3544 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3545 pointer->absMTWidthMinor = rawEvent->value;
3546 break;
3547 case ABS_MT_ORIENTATION:
3548 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3549 pointer->absMTOrientation = rawEvent->value;
3550 break;
3551 case ABS_MT_TRACKING_ID:
3552 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3553 pointer->absMTTrackingId = rawEvent->value;
3554 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003555 case ABS_MT_PRESSURE:
3556 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3557 pointer->absMTPressure = rawEvent->value;
3558 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003559 }
3560 break;
3561 }
3562
3563 case EV_SYN:
3564 switch (rawEvent->scanCode) {
3565 case SYN_MT_REPORT: {
3566 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3567 uint32_t pointerIndex = mAccumulator.pointerCount;
3568
3569 if (mAccumulator.pointers[pointerIndex].fields) {
3570 if (pointerIndex == MAX_POINTERS) {
3571 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3572 MAX_POINTERS);
3573 } else {
3574 pointerIndex += 1;
3575 mAccumulator.pointerCount = pointerIndex;
3576 }
3577 }
3578
3579 mAccumulator.pointers[pointerIndex].clear();
3580 break;
3581 }
3582
3583 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003584 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003585 break;
3586 }
3587 break;
3588 }
3589}
3590
3591void MultiTouchInputMapper::sync(nsecs_t when) {
3592 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003593 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003594
Jeff Brown6d0fec22010-07-23 21:28:06 -07003595 uint32_t inCount = mAccumulator.pointerCount;
3596 uint32_t outCount = 0;
3597 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003598
Jeff Brown6d0fec22010-07-23 21:28:06 -07003599 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003600
Jeff Brown6d0fec22010-07-23 21:28:06 -07003601 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003602 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3603 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003604
Jeff Brown6d0fec22010-07-23 21:28:06 -07003605 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003606 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3607 // Drop this finger.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003608 continue;
3609 }
3610
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003611 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3612 outPointer.x = inPointer.absMTPositionX;
3613 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003614
Jeff Brown8d608662010-08-30 03:02:23 -07003615 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3616 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003617 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3618 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003619 continue;
3620 }
Jeff Brown8d608662010-08-30 03:02:23 -07003621 outPointer.pressure = inPointer.absMTPressure;
3622 } else {
3623 // Default pressure to 0 if absent.
3624 outPointer.pressure = 0;
3625 }
3626
3627 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3628 if (inPointer.absMTTouchMajor <= 0) {
3629 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3630 // a pointer going up. Drop this finger.
3631 continue;
3632 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003633 outPointer.touchMajor = inPointer.absMTTouchMajor;
3634 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003635 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003636 outPointer.touchMajor = 0;
3637 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003638
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003639 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3640 outPointer.touchMinor = inPointer.absMTTouchMinor;
3641 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003642 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003643 outPointer.touchMinor = outPointer.touchMajor;
3644 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003645
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003646 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3647 outPointer.toolMajor = inPointer.absMTWidthMajor;
3648 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003649 // Default tool area to 0 if absent.
3650 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003651 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003652
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003653 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3654 outPointer.toolMinor = inPointer.absMTWidthMinor;
3655 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003656 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003657 outPointer.toolMinor = outPointer.toolMajor;
3658 }
3659
3660 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3661 outPointer.orientation = inPointer.absMTOrientation;
3662 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003663 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003664 outPointer.orientation = 0;
3665 }
3666
Jeff Brown8d608662010-08-30 03:02:23 -07003667 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003668 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003669 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3670 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003671
Jeff Brown6d0fec22010-07-23 21:28:06 -07003672 if (id > MAX_POINTER_ID) {
3673#if DEBUG_POINTERS
3674 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003675 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003676 id, MAX_POINTER_ID);
3677#endif
3678 havePointerIds = false;
3679 }
3680 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003681 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003682 mCurrentTouch.idToIndex[id] = outCount;
3683 mCurrentTouch.idBits.markBit(id);
3684 }
3685 } else {
3686 havePointerIds = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003687 }
3688 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003689
Jeff Brown6d0fec22010-07-23 21:28:06 -07003690 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003691 }
3692
Jeff Brown6d0fec22010-07-23 21:28:06 -07003693 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003694
Jeff Brown6d0fec22010-07-23 21:28:06 -07003695 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003696
3697 mAccumulator.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003698}
3699
Jeff Brown8d608662010-08-30 03:02:23 -07003700void MultiTouchInputMapper::configureRawAxes() {
3701 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003702
Jeff Brown8d608662010-08-30 03:02:23 -07003703 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3704 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3705 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3706 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3707 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3708 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3709 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3710 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003711}
3712
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003713
Jeff Browncb1404e2011-01-15 18:14:15 -08003714// --- JoystickInputMapper ---
3715
3716JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3717 InputMapper(device) {
3718 initialize();
3719}
3720
3721JoystickInputMapper::~JoystickInputMapper() {
3722}
3723
3724uint32_t JoystickInputMapper::getSources() {
3725 return AINPUT_SOURCE_JOYSTICK;
3726}
3727
3728void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3729 InputMapper::populateDeviceInfo(info);
3730
3731 if (mAxes.x.valid) {
3732 info->addMotionRange(AINPUT_MOTION_RANGE_X,
3733 mAxes.x.min, mAxes.x.max, mAxes.x.flat, mAxes.x.fuzz);
3734 }
3735 if (mAxes.y.valid) {
3736 info->addMotionRange(AINPUT_MOTION_RANGE_Y,
3737 mAxes.y.min, mAxes.y.max, mAxes.y.flat, mAxes.y.fuzz);
3738 }
3739}
3740
3741void JoystickInputMapper::dump(String8& dump) {
3742 dump.append(INDENT2 "Joystick Input Mapper:\n");
3743
3744 dump.append(INDENT3 "Raw Axes:\n");
3745 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
3746 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
3747
3748 dump.append(INDENT3 "Normalized Axes:\n");
3749 dumpNormalizedAxis(dump, mAxes.x, "X");
3750 dumpNormalizedAxis(dump, mAxes.y, "Y");
3751 dumpNormalizedAxis(dump, mAxes.hat0X, "Hat0X");
3752 dumpNormalizedAxis(dump, mAxes.hat0Y, "Hat0Y");
3753}
3754
3755void JoystickInputMapper::dumpNormalizedAxis(String8& dump,
3756 const NormalizedAxis& axis, const char* name) {
3757 if (axis.valid) {
3758 dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
3759 "scale=%0.3f, center=%0.3f, precision=%0.3f, value=%0.3f\n",
3760 name, axis.min, axis.max, axis.flat, axis.fuzz,
3761 axis.scale, axis.center, axis.precision, axis.value);
3762 } else {
3763 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
3764 }
3765}
3766
3767void JoystickInputMapper::configure() {
3768 InputMapper::configure();
3769
3770 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3771 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3772 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_HAT0X, & mRawAxes.hat0X);
3773 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_HAT0Y, & mRawAxes.hat0Y);
3774
3775 mAxes.x.configure(mRawAxes.x);
3776 mAxes.y.configure(mRawAxes.y);
3777 mAxes.hat0X.configure(mRawAxes.hat0X);
3778 mAxes.hat0Y.configure(mRawAxes.hat0Y);
3779}
3780
3781void JoystickInputMapper::initialize() {
3782 mAccumulator.clear();
3783
3784 mAxes.x.resetState();
3785 mAxes.y.resetState();
3786 mAxes.hat0X.resetState();
3787 mAxes.hat0Y.resetState();
3788}
3789
3790void JoystickInputMapper::reset() {
3791 // Recenter all axes.
3792 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
3793 mAccumulator.clear();
3794 mAccumulator.fields = Accumulator::FIELD_ALL;
3795 sync(when);
3796
3797 // Reinitialize state.
3798 initialize();
3799
3800 InputMapper::reset();
3801}
3802
3803void JoystickInputMapper::process(const RawEvent* rawEvent) {
3804 switch (rawEvent->type) {
3805 case EV_ABS:
3806 switch (rawEvent->scanCode) {
3807 case ABS_X:
3808 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3809 mAccumulator.absX = rawEvent->value;
3810 break;
3811 case ABS_Y:
3812 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3813 mAccumulator.absY = rawEvent->value;
3814 break;
3815 case ABS_HAT0X:
3816 mAccumulator.fields |= Accumulator::FIELD_ABS_HAT0X;
3817 mAccumulator.absHat0X = rawEvent->value;
3818 break;
3819 case ABS_HAT0Y:
3820 mAccumulator.fields |= Accumulator::FIELD_ABS_HAT0Y;
3821 mAccumulator.absHat0Y = rawEvent->value;
3822 break;
3823 }
3824 break;
3825
3826 case EV_SYN:
3827 switch (rawEvent->scanCode) {
3828 case SYN_REPORT:
3829 sync(rawEvent->when);
3830 break;
3831 }
3832 break;
3833 }
3834}
3835
3836void JoystickInputMapper::sync(nsecs_t when) {
3837 uint32_t fields = mAccumulator.fields;
3838 if (fields == 0) {
3839 return; // no new state changes, so nothing to do
3840 }
3841
3842 int32_t metaState = mContext->getGlobalMetaState();
3843
3844 bool motionAxisChanged = false;
3845 if (fields & Accumulator::FIELD_ABS_X) {
3846 if (mAxes.x.updateValue(mAccumulator.absX)) {
3847 motionAxisChanged = true;
3848 }
3849 }
3850
3851 if (fields & Accumulator::FIELD_ABS_Y) {
3852 if (mAxes.y.updateValue(mAccumulator.absY)) {
3853 motionAxisChanged = true;
3854 }
3855 }
3856
3857 if (motionAxisChanged) {
3858 PointerCoords pointerCoords;
Jeff Brown91c69ab2011-02-14 17:03:18 -08003859 pointerCoords.clear();
3860 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_X, mAxes.x.value);
3861 pointerCoords.setAxisValue(AINPUT_MOTION_AXIS_Y, mAxes.y.value);
Jeff Browncb1404e2011-01-15 18:14:15 -08003862
3863 int32_t pointerId = 0;
3864 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3865 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3866 1, &pointerId, &pointerCoords, mAxes.x.precision, mAxes.y.precision, 0);
3867 }
3868
3869 if (fields & Accumulator::FIELD_ABS_HAT0X) {
3870 if (mAxes.hat0X.updateValueAndDirection(mAccumulator.absHat0X)) {
3871 notifyDirectionalAxis(mAxes.hat0X, when, metaState,
3872 AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT);
3873 }
3874 }
3875
3876 if (fields & Accumulator::FIELD_ABS_HAT0Y) {
3877 if (mAxes.hat0Y.updateValueAndDirection(mAccumulator.absHat0Y)) {
3878 notifyDirectionalAxis(mAxes.hat0Y, when, metaState,
3879 AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN);
3880 }
3881 }
3882
3883 mAccumulator.clear();
3884}
3885
3886void JoystickInputMapper::notifyDirectionalAxis(DirectionalAxis& axis,
3887 nsecs_t when, int32_t metaState, int32_t lowKeyCode, int32_t highKeyCode) {
3888 if (axis.lastKeyCode) {
3889 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3890 AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM,
3891 axis.lastKeyCode, 0, metaState, when);
3892 axis.lastKeyCode = 0;
3893 }
3894 if (axis.direction) {
3895 axis.lastKeyCode = axis.direction > 0 ? highKeyCode : lowKeyCode;
3896 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
3897 AKEY_EVENT_ACTION_DOWN, AKEY_EVENT_FLAG_FROM_SYSTEM,
3898 axis.lastKeyCode, 0, metaState, when);
3899 }
3900}
3901
3902
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003903} // namespace android