blob: 6b6679117fab74d3a5ca3345b227f1271dd28284 [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac02010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036#include "InputReader.h"
37
Jeff Brown46b9ac02010-04-22 18:58:52 -070038#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080039#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080040#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070045#include <errno.h>
46#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070047#include <math.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070048
Jeff Brown8d608662010-08-30 03:02:23 -070049#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070050#define INDENT2 " "
51#define INDENT3 " "
52#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070053
Jeff Brown46b9ac02010-04-22 18:58:52 -070054namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60 return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65 return a < b ? a : b;
66}
67
Jeff Brown5c225b12010-06-16 01:53:36 -070068template<typename T>
69inline static void swap(T& a, T& b) {
70 T temp = a;
71 a = b;
72 b = temp;
73}
74
Jeff Brown8d608662010-08-30 03:02:23 -070075inline static float avg(float x, float y) {
76 return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80 return sqrtf(x * x + y * y);
81}
82
Jeff Brown517bb4c2011-01-14 19:09:23 -080083inline static int32_t signExtendNybble(int32_t value) {
84 return value >= 8 ? value - 16 : value;
85}
86
Jeff Brownef3d7e82010-09-30 14:33:04 -070087static inline const char* toString(bool value) {
88 return value ? "true" : "false";
89}
90
Jeff Brown46b9ac02010-04-22 18:58:52 -070091static const int32_t keyCodeRotationMap[][4] = {
92 // key codes enumerated counter-clockwise with the original (unrotated) key first
93 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -070094 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
95 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
96 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
97 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac02010-04-22 18:58:52 -070098};
99static const int keyCodeRotationMapSize =
100 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
101
102int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800103 if (orientation != DISPLAY_ORIENTATION_0) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700104 for (int i = 0; i < keyCodeRotationMapSize; i++) {
105 if (keyCode == keyCodeRotationMap[i][0]) {
106 return keyCodeRotationMap[i][orientation];
107 }
108 }
109 }
110 return keyCode;
111}
112
Jeff Brown6d0fec22010-07-23 21:28:06 -0700113static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
114 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
115}
116
Jeff Brown46b9ac02010-04-22 18:58:52 -0700117
Jeff Brown46b9ac02010-04-22 18:58:52 -0700118// --- InputReader ---
119
120InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700121 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700122 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700123 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
124 mGlobalMetaState(0) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700125 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700126 updateGlobalMetaState();
127 updateInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700128}
129
130InputReader::~InputReader() {
131 for (size_t i = 0; i < mDevices.size(); i++) {
132 delete mDevices.valueAt(i);
133 }
134}
135
136void InputReader::loopOnce() {
137 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700138 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700139
140#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800141 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700142 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
143 rawEvent.value);
144#endif
145
146 process(& rawEvent);
147}
148
149void InputReader::process(const RawEvent* rawEvent) {
150 switch (rawEvent->type) {
151 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700152 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700153 break;
154
155 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700156 removeDevice(rawEvent->deviceId);
157 break;
158
159 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700160 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700161 break;
162
Jeff Brown6d0fec22010-07-23 21:28:06 -0700163 default:
164 consumeEvent(rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700165 break;
166 }
167}
168
Jeff Brown7342bb92010-10-01 18:55:43 -0700169void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700170 String8 name = mEventHub->getDeviceName(deviceId);
171 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
172
173 InputDevice* device = createDevice(deviceId, name, classes);
174 device->configure();
175
Jeff Brown8d608662010-08-30 03:02:23 -0700176 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800177 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700178 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800179 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700180 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700181 }
182
Jeff Brown6d0fec22010-07-23 21:28:06 -0700183 bool added = false;
184 { // acquire device registry writer lock
185 RWLock::AutoWLock _wl(mDeviceRegistryLock);
186
187 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
188 if (deviceIndex < 0) {
189 mDevices.add(deviceId, device);
190 added = true;
191 }
192 } // release device registry writer lock
193
194 if (! added) {
195 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
196 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700197 return;
198 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700199}
200
Jeff Brown7342bb92010-10-01 18:55:43 -0700201void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700202 bool removed = false;
203 InputDevice* device = NULL;
204 { // acquire device registry writer lock
205 RWLock::AutoWLock _wl(mDeviceRegistryLock);
206
207 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
208 if (deviceIndex >= 0) {
209 device = mDevices.valueAt(deviceIndex);
210 mDevices.removeItemsAt(deviceIndex, 1);
211 removed = true;
212 }
213 } // release device registry writer lock
214
215 if (! removed) {
216 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700217 return;
218 }
219
Jeff Brown6d0fec22010-07-23 21:28:06 -0700220 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800221 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700222 device->getId(), device->getName().string());
223 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800224 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700225 device->getId(), device->getName().string(), device->getSources());
226 }
227
Jeff Brown8d608662010-08-30 03:02:23 -0700228 device->reset();
229
Jeff Brown6d0fec22010-07-23 21:28:06 -0700230 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700231}
232
Jeff Brown6d0fec22010-07-23 21:28:06 -0700233InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
234 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700235
Jeff Brown6d0fec22010-07-23 21:28:06 -0700236 // Switch-like devices.
237 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
238 device->addMapper(new SwitchInputMapper(device));
239 }
240
241 // Keyboard-like devices.
242 uint32_t keyboardSources = 0;
243 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
244 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
245 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
246 }
247 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
248 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
249 }
250 if (classes & INPUT_DEVICE_CLASS_DPAD) {
251 keyboardSources |= AINPUT_SOURCE_DPAD;
252 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700253
254 if (keyboardSources != 0) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800255 device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700256 }
257
Jeff Brown83c09682010-12-23 17:50:18 -0800258 // Cursor-like devices.
259 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
260 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700261 }
262
263 // Touchscreen-like devices.
264 if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800265 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700266 } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800267 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700268 }
269
270 return device;
271}
272
273void InputReader::consumeEvent(const RawEvent* rawEvent) {
274 int32_t deviceId = rawEvent->deviceId;
275
276 { // acquire device registry reader lock
277 RWLock::AutoRLock _rl(mDeviceRegistryLock);
278
279 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
280 if (deviceIndex < 0) {
281 LOGW("Discarding event for unknown deviceId %d.", deviceId);
282 return;
283 }
284
285 InputDevice* device = mDevices.valueAt(deviceIndex);
286 if (device->isIgnored()) {
287 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
288 return;
289 }
290
291 device->process(rawEvent);
292 } // release device registry reader lock
293}
294
Jeff Brownc3db8582010-10-20 15:33:38 -0700295void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700296 // Reset global meta state because it depends on the list of all configured devices.
297 updateGlobalMetaState();
298
299 // Update input configuration.
300 updateInputConfiguration();
301
302 // Enqueue configuration changed.
303 mDispatcher->notifyConfigurationChanged(when);
304}
305
306void InputReader::configureExcludedDevices() {
307 Vector<String8> excludedDeviceNames;
308 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
309
310 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
311 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
312 }
313}
314
315void InputReader::updateGlobalMetaState() {
316 { // acquire state lock
317 AutoMutex _l(mStateLock);
318
319 mGlobalMetaState = 0;
320
321 { // acquire device registry reader lock
322 RWLock::AutoRLock _rl(mDeviceRegistryLock);
323
324 for (size_t i = 0; i < mDevices.size(); i++) {
325 InputDevice* device = mDevices.valueAt(i);
326 mGlobalMetaState |= device->getMetaState();
327 }
328 } // release device registry reader lock
329 } // release state lock
330}
331
332int32_t InputReader::getGlobalMetaState() {
333 { // acquire state lock
334 AutoMutex _l(mStateLock);
335
336 return mGlobalMetaState;
337 } // release state lock
338}
339
340void InputReader::updateInputConfiguration() {
341 { // acquire state lock
342 AutoMutex _l(mStateLock);
343
344 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
345 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
346 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
347 { // acquire device registry reader lock
348 RWLock::AutoRLock _rl(mDeviceRegistryLock);
349
350 InputDeviceInfo deviceInfo;
351 for (size_t i = 0; i < mDevices.size(); i++) {
352 InputDevice* device = mDevices.valueAt(i);
353 device->getDeviceInfo(& deviceInfo);
354 uint32_t sources = deviceInfo.getSources();
355
356 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
357 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
358 }
359 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
360 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
361 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
362 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
363 }
364 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
365 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700366 }
367 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700368 } // release device registry reader lock
Jeff Brown46b9ac02010-04-22 18:58:52 -0700369
Jeff Brown6d0fec22010-07-23 21:28:06 -0700370 mInputConfiguration.touchScreen = touchScreenConfig;
371 mInputConfiguration.keyboard = keyboardConfig;
372 mInputConfiguration.navigation = navigationConfig;
373 } // release state lock
374}
375
376void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
377 { // acquire state lock
378 AutoMutex _l(mStateLock);
379
380 *outConfiguration = mInputConfiguration;
381 } // release state lock
382}
383
384status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
385 { // acquire device registry reader lock
386 RWLock::AutoRLock _rl(mDeviceRegistryLock);
387
388 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
389 if (deviceIndex < 0) {
390 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700391 }
392
Jeff Brown6d0fec22010-07-23 21:28:06 -0700393 InputDevice* device = mDevices.valueAt(deviceIndex);
394 if (device->isIgnored()) {
395 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700396 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700397
398 device->getDeviceInfo(outDeviceInfo);
399 return OK;
400 } // release device registy reader lock
401}
402
403void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
404 outDeviceIds.clear();
405
406 { // acquire device registry reader lock
407 RWLock::AutoRLock _rl(mDeviceRegistryLock);
408
409 size_t numDevices = mDevices.size();
410 for (size_t i = 0; i < numDevices; i++) {
411 InputDevice* device = mDevices.valueAt(i);
412 if (! device->isIgnored()) {
413 outDeviceIds.add(device->getId());
414 }
415 }
416 } // release device registy reader lock
417}
418
419int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
420 int32_t keyCode) {
421 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
422}
423
424int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
425 int32_t scanCode) {
426 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
427}
428
429int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
430 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
431}
432
433int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
434 GetStateFunc getStateFunc) {
435 { // acquire device registry reader lock
436 RWLock::AutoRLock _rl(mDeviceRegistryLock);
437
438 int32_t result = AKEY_STATE_UNKNOWN;
439 if (deviceId >= 0) {
440 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
441 if (deviceIndex >= 0) {
442 InputDevice* device = mDevices.valueAt(deviceIndex);
443 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
444 result = (device->*getStateFunc)(sourceMask, code);
445 }
446 }
447 } else {
448 size_t numDevices = mDevices.size();
449 for (size_t i = 0; i < numDevices; i++) {
450 InputDevice* device = mDevices.valueAt(i);
451 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
452 result = (device->*getStateFunc)(sourceMask, code);
453 if (result >= AKEY_STATE_DOWN) {
454 return result;
455 }
456 }
457 }
458 }
459 return result;
460 } // release device registy reader lock
461}
462
463bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
464 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
465 memset(outFlags, 0, numCodes);
466 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
467}
468
469bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
470 const int32_t* keyCodes, uint8_t* outFlags) {
471 { // acquire device registry reader lock
472 RWLock::AutoRLock _rl(mDeviceRegistryLock);
473 bool result = false;
474 if (deviceId >= 0) {
475 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
476 if (deviceIndex >= 0) {
477 InputDevice* device = mDevices.valueAt(deviceIndex);
478 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
479 result = device->markSupportedKeyCodes(sourceMask,
480 numCodes, keyCodes, outFlags);
481 }
482 }
483 } else {
484 size_t numDevices = mDevices.size();
485 for (size_t i = 0; i < numDevices; i++) {
486 InputDevice* device = mDevices.valueAt(i);
487 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
488 result |= device->markSupportedKeyCodes(sourceMask,
489 numCodes, keyCodes, outFlags);
490 }
491 }
492 }
493 return result;
494 } // release device registy reader lock
495}
496
Jeff Brownb88102f2010-09-08 11:49:43 -0700497void InputReader::dump(String8& dump) {
Jeff Brownf2f48712010-10-01 17:46:21 -0700498 mEventHub->dump(dump);
499 dump.append("\n");
500
501 dump.append("Input Reader State:\n");
502
Jeff Brownef3d7e82010-09-30 14:33:04 -0700503 { // acquire device registry reader lock
504 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700505
Jeff Brownef3d7e82010-09-30 14:33:04 -0700506 for (size_t i = 0; i < mDevices.size(); i++) {
507 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700508 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700509 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700510}
511
Jeff Brown6d0fec22010-07-23 21:28:06 -0700512
513// --- InputReaderThread ---
514
515InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
516 Thread(/*canCallJava*/ true), mReader(reader) {
517}
518
519InputReaderThread::~InputReaderThread() {
520}
521
522bool InputReaderThread::threadLoop() {
523 mReader->loopOnce();
524 return true;
525}
526
527
528// --- InputDevice ---
529
530InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
531 mContext(context), mId(id), mName(name), mSources(0) {
532}
533
534InputDevice::~InputDevice() {
535 size_t numMappers = mMappers.size();
536 for (size_t i = 0; i < numMappers; i++) {
537 delete mMappers[i];
538 }
539 mMappers.clear();
540}
541
Jeff Brownef3d7e82010-09-30 14:33:04 -0700542static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
543 int32_t rangeType, const char* name) {
544 const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
545 if (range) {
546 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
547 name, range->min, range->max, range->flat, range->fuzz);
548 }
549}
550
551void InputDevice::dump(String8& dump) {
552 InputDeviceInfo deviceInfo;
553 getDeviceInfo(& deviceInfo);
554
Jeff Brown90655042010-12-02 13:50:46 -0800555 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700556 deviceInfo.getName().string());
557 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
558 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
559 if (!deviceInfo.getMotionRanges().isEmpty()) {
560 dump.append(INDENT2 "Motion Ranges:\n");
561 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
562 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
563 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
564 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
565 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
566 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
567 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
568 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
569 dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
570 }
571
572 size_t numMappers = mMappers.size();
573 for (size_t i = 0; i < numMappers; i++) {
574 InputMapper* mapper = mMappers[i];
575 mapper->dump(dump);
576 }
577}
578
Jeff Brown6d0fec22010-07-23 21:28:06 -0700579void InputDevice::addMapper(InputMapper* mapper) {
580 mMappers.add(mapper);
581}
582
583void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700584 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800585 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700586 }
587
Jeff Brown6d0fec22010-07-23 21:28:06 -0700588 mSources = 0;
589
590 size_t numMappers = mMappers.size();
591 for (size_t i = 0; i < numMappers; i++) {
592 InputMapper* mapper = mMappers[i];
593 mapper->configure();
594 mSources |= mapper->getSources();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700595 }
596}
597
Jeff Brown6d0fec22010-07-23 21:28:06 -0700598void InputDevice::reset() {
599 size_t numMappers = mMappers.size();
600 for (size_t i = 0; i < numMappers; i++) {
601 InputMapper* mapper = mMappers[i];
602 mapper->reset();
603 }
604}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700605
Jeff Brown6d0fec22010-07-23 21:28:06 -0700606void InputDevice::process(const RawEvent* rawEvent) {
607 size_t numMappers = mMappers.size();
608 for (size_t i = 0; i < numMappers; i++) {
609 InputMapper* mapper = mMappers[i];
610 mapper->process(rawEvent);
611 }
612}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700613
Jeff Brown6d0fec22010-07-23 21:28:06 -0700614void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
615 outDeviceInfo->initialize(mId, mName);
616
617 size_t numMappers = mMappers.size();
618 for (size_t i = 0; i < numMappers; i++) {
619 InputMapper* mapper = mMappers[i];
620 mapper->populateDeviceInfo(outDeviceInfo);
621 }
622}
623
624int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
625 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
626}
627
628int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
629 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
630}
631
632int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
633 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
634}
635
636int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
637 int32_t result = AKEY_STATE_UNKNOWN;
638 size_t numMappers = mMappers.size();
639 for (size_t i = 0; i < numMappers; i++) {
640 InputMapper* mapper = mMappers[i];
641 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
642 result = (mapper->*getStateFunc)(sourceMask, code);
643 if (result >= AKEY_STATE_DOWN) {
644 return result;
645 }
646 }
647 }
648 return result;
649}
650
651bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
652 const int32_t* keyCodes, uint8_t* outFlags) {
653 bool result = false;
654 size_t numMappers = mMappers.size();
655 for (size_t i = 0; i < numMappers; i++) {
656 InputMapper* mapper = mMappers[i];
657 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
658 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
659 }
660 }
661 return result;
662}
663
664int32_t InputDevice::getMetaState() {
665 int32_t result = 0;
666 size_t numMappers = mMappers.size();
667 for (size_t i = 0; i < numMappers; i++) {
668 InputMapper* mapper = mMappers[i];
669 result |= mapper->getMetaState();
670 }
671 return result;
672}
673
674
675// --- InputMapper ---
676
677InputMapper::InputMapper(InputDevice* device) :
678 mDevice(device), mContext(device->getContext()) {
679}
680
681InputMapper::~InputMapper() {
682}
683
684void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
685 info->addSource(getSources());
686}
687
Jeff Brownef3d7e82010-09-30 14:33:04 -0700688void InputMapper::dump(String8& dump) {
689}
690
Jeff Brown6d0fec22010-07-23 21:28:06 -0700691void InputMapper::configure() {
692}
693
694void InputMapper::reset() {
695}
696
697int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
698 return AKEY_STATE_UNKNOWN;
699}
700
701int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
702 return AKEY_STATE_UNKNOWN;
703}
704
705int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
706 return AKEY_STATE_UNKNOWN;
707}
708
709bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
710 const int32_t* keyCodes, uint8_t* outFlags) {
711 return false;
712}
713
714int32_t InputMapper::getMetaState() {
715 return 0;
716}
717
Jeff Brown6d0fec22010-07-23 21:28:06 -0700718
719// --- SwitchInputMapper ---
720
721SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
722 InputMapper(device) {
723}
724
725SwitchInputMapper::~SwitchInputMapper() {
726}
727
728uint32_t SwitchInputMapper::getSources() {
729 return 0;
730}
731
732void SwitchInputMapper::process(const RawEvent* rawEvent) {
733 switch (rawEvent->type) {
734 case EV_SW:
735 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
736 break;
737 }
738}
739
740void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700741 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700742}
743
744int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
745 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
746}
747
748
749// --- KeyboardInputMapper ---
750
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800751KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700752 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800753 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700754 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700755 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700756}
757
758KeyboardInputMapper::~KeyboardInputMapper() {
759}
760
Jeff Brown6328cdc2010-07-29 18:18:33 -0700761void KeyboardInputMapper::initializeLocked() {
762 mLocked.metaState = AMETA_NONE;
763 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700764}
765
766uint32_t KeyboardInputMapper::getSources() {
767 return mSources;
768}
769
770void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
771 InputMapper::populateDeviceInfo(info);
772
773 info->setKeyboardType(mKeyboardType);
774}
775
Jeff Brownef3d7e82010-09-30 14:33:04 -0700776void KeyboardInputMapper::dump(String8& dump) {
777 { // acquire lock
778 AutoMutex _l(mLock);
779 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800780 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700781 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
782 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
783 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
784 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
785 } // release lock
786}
787
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800788
789void KeyboardInputMapper::configure() {
790 InputMapper::configure();
791
792 // Configure basic parameters.
793 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800794
795 // Reset LEDs.
796 {
797 AutoMutex _l(mLock);
798 resetLedStateLocked();
799 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800800}
801
802void KeyboardInputMapper::configureParameters() {
803 mParameters.orientationAware = false;
804 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
805 mParameters.orientationAware);
806
807 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
808}
809
810void KeyboardInputMapper::dumpParameters(String8& dump) {
811 dump.append(INDENT3 "Parameters:\n");
812 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
813 mParameters.associatedDisplayId);
814 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
815 toString(mParameters.orientationAware));
816}
817
Jeff Brown6d0fec22010-07-23 21:28:06 -0700818void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700819 for (;;) {
820 int32_t keyCode, scanCode;
821 { // acquire lock
822 AutoMutex _l(mLock);
823
824 // Synthesize key up event on reset if keys are currently down.
825 if (mLocked.keyDowns.isEmpty()) {
826 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800827 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700828 break; // done
829 }
830
831 const KeyDown& keyDown = mLocked.keyDowns.top();
832 keyCode = keyDown.keyCode;
833 scanCode = keyDown.scanCode;
834 } // release lock
835
Jeff Brown6d0fec22010-07-23 21:28:06 -0700836 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700837 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700838 }
839
840 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700841 getContext()->updateGlobalMetaState();
842}
843
844void KeyboardInputMapper::process(const RawEvent* rawEvent) {
845 switch (rawEvent->type) {
846 case EV_KEY: {
847 int32_t scanCode = rawEvent->scanCode;
848 if (isKeyboardOrGamepadKey(scanCode)) {
849 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
850 rawEvent->flags);
851 }
852 break;
853 }
854 }
855}
856
857bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
858 return scanCode < BTN_MOUSE
859 || scanCode >= KEY_OK
860 || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
861}
862
Jeff Brown6328cdc2010-07-29 18:18:33 -0700863void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
864 int32_t scanCode, uint32_t policyFlags) {
865 int32_t newMetaState;
866 nsecs_t downTime;
867 bool metaStateChanged = false;
868
869 { // acquire lock
870 AutoMutex _l(mLock);
871
872 if (down) {
873 // Rotate key codes according to orientation if needed.
874 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800875 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700876 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800877 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
878 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800879 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700880 }
881
882 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700883 }
884
Jeff Brown6328cdc2010-07-29 18:18:33 -0700885 // Add key down.
886 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
887 if (keyDownIndex >= 0) {
888 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800889 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700890 } else {
891 // key down
892 mLocked.keyDowns.push();
893 KeyDown& keyDown = mLocked.keyDowns.editTop();
894 keyDown.keyCode = keyCode;
895 keyDown.scanCode = scanCode;
896 }
897
898 mLocked.downTime = when;
899 } else {
900 // Remove key down.
901 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
902 if (keyDownIndex >= 0) {
903 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800904 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700905 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
906 } else {
907 // key was not actually down
908 LOGI("Dropping key up from device %s because the key was not down. "
909 "keyCode=%d, scanCode=%d",
910 getDeviceName().string(), keyCode, scanCode);
911 return;
912 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700913 }
914
Jeff Brown6328cdc2010-07-29 18:18:33 -0700915 int32_t oldMetaState = mLocked.metaState;
916 newMetaState = updateMetaState(keyCode, down, oldMetaState);
917 if (oldMetaState != newMetaState) {
918 mLocked.metaState = newMetaState;
919 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -0700920 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700921 }
Jeff Brownfd035822010-06-30 16:10:35 -0700922
Jeff Brown6328cdc2010-07-29 18:18:33 -0700923 downTime = mLocked.downTime;
924 } // release lock
925
926 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700927 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700928 }
929
Jeff Brown497a92c2010-09-12 17:55:08 -0700930 if (policyFlags & POLICY_FLAG_FUNCTION) {
931 newMetaState |= AMETA_FUNCTION_ON;
932 }
Jeff Brown83c09682010-12-23 17:50:18 -0800933 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -0700934 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
935 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700936}
937
Jeff Brown6328cdc2010-07-29 18:18:33 -0700938ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
939 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700940 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700941 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700942 return i;
943 }
944 }
945 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700946}
947
Jeff Brown6d0fec22010-07-23 21:28:06 -0700948int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
949 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
950}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700951
Jeff Brown6d0fec22010-07-23 21:28:06 -0700952int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
953 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
954}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700955
Jeff Brown6d0fec22010-07-23 21:28:06 -0700956bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
957 const int32_t* keyCodes, uint8_t* outFlags) {
958 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
959}
960
961int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700962 { // acquire lock
963 AutoMutex _l(mLock);
964 return mLocked.metaState;
965 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -0700966}
967
Jeff Brown49ed71d2010-12-06 17:13:33 -0800968void KeyboardInputMapper::resetLedStateLocked() {
969 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
970 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
971 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
972
973 updateLedStateLocked(true);
974}
975
976void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
977 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
978 ledState.on = false;
979}
980
Jeff Brown497a92c2010-09-12 17:55:08 -0700981void KeyboardInputMapper::updateLedStateLocked(bool reset) {
982 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -0700983 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -0700984 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -0700985 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -0700986 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -0700987 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -0700988}
989
990void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
991 int32_t led, int32_t modifier, bool reset) {
992 if (ledState.avail) {
993 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800994 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -0700995 getEventHub()->setLedState(getDeviceId(), led, desiredState);
996 ledState.on = desiredState;
997 }
998 }
999}
1000
Jeff Brown6d0fec22010-07-23 21:28:06 -07001001
Jeff Brown83c09682010-12-23 17:50:18 -08001002// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001003
Jeff Brown83c09682010-12-23 17:50:18 -08001004CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001005 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001006 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001007}
1008
Jeff Brown83c09682010-12-23 17:50:18 -08001009CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001010}
1011
Jeff Brown83c09682010-12-23 17:50:18 -08001012uint32_t CursorInputMapper::getSources() {
1013 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001014}
1015
Jeff Brown83c09682010-12-23 17:50:18 -08001016void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001017 InputMapper::populateDeviceInfo(info);
1018
Jeff Brown83c09682010-12-23 17:50:18 -08001019 if (mParameters.mode == Parameters::MODE_POINTER) {
1020 float minX, minY, maxX, maxY;
1021 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1022 info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f);
1023 info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f);
1024 }
1025 } else {
1026 info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
1027 info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
1028 }
1029 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001030}
1031
Jeff Brown83c09682010-12-23 17:50:18 -08001032void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001033 { // acquire lock
1034 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001035 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001036 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001037 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1038 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
1039 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1040 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1041 } // release lock
1042}
1043
Jeff Brown83c09682010-12-23 17:50:18 -08001044void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001045 InputMapper::configure();
1046
1047 // Configure basic parameters.
1048 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001049
1050 // Configure device mode.
1051 switch (mParameters.mode) {
1052 case Parameters::MODE_POINTER:
1053 mSources = AINPUT_SOURCE_MOUSE;
1054 mXPrecision = 1.0f;
1055 mYPrecision = 1.0f;
1056 mXScale = 1.0f;
1057 mYScale = 1.0f;
1058 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1059 break;
1060 case Parameters::MODE_NAVIGATION:
1061 mSources = AINPUT_SOURCE_TRACKBALL;
1062 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1063 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1064 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1065 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1066 break;
1067 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001068}
1069
Jeff Brown83c09682010-12-23 17:50:18 -08001070void CursorInputMapper::configureParameters() {
1071 mParameters.mode = Parameters::MODE_POINTER;
1072 String8 cursorModeString;
1073 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1074 if (cursorModeString == "navigation") {
1075 mParameters.mode = Parameters::MODE_NAVIGATION;
1076 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1077 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1078 }
1079 }
1080
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001081 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001082 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001083 mParameters.orientationAware);
1084
Jeff Brown83c09682010-12-23 17:50:18 -08001085 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1086 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001087}
1088
Jeff Brown83c09682010-12-23 17:50:18 -08001089void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001090 dump.append(INDENT3 "Parameters:\n");
1091 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1092 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001093
1094 switch (mParameters.mode) {
1095 case Parameters::MODE_POINTER:
1096 dump.append(INDENT4 "Mode: pointer\n");
1097 break;
1098 case Parameters::MODE_NAVIGATION:
1099 dump.append(INDENT4 "Mode: navigation\n");
1100 break;
1101 default:
1102 assert(false);
1103 }
1104
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001105 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1106 toString(mParameters.orientationAware));
1107}
1108
Jeff Brown83c09682010-12-23 17:50:18 -08001109void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001110 mAccumulator.clear();
1111
Jeff Brown6328cdc2010-07-29 18:18:33 -07001112 mLocked.down = false;
1113 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001114}
1115
Jeff Brown83c09682010-12-23 17:50:18 -08001116void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001117 for (;;) {
1118 { // acquire lock
1119 AutoMutex _l(mLock);
1120
1121 if (! mLocked.down) {
1122 initializeLocked();
1123 break; // done
1124 }
1125 } // release lock
1126
Jeff Brown83c09682010-12-23 17:50:18 -08001127 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001128 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001129 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001130 mAccumulator.btnMouse = false;
1131 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001132 }
1133
Jeff Brown6d0fec22010-07-23 21:28:06 -07001134 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001135}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001136
Jeff Brown83c09682010-12-23 17:50:18 -08001137void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001138 switch (rawEvent->type) {
1139 case EV_KEY:
1140 switch (rawEvent->scanCode) {
1141 case BTN_MOUSE:
1142 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1143 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001144 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1145 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001146 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001147 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001148 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001149 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001150
Jeff Brown6d0fec22010-07-23 21:28:06 -07001151 case EV_REL:
1152 switch (rawEvent->scanCode) {
1153 case REL_X:
1154 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1155 mAccumulator.relX = rawEvent->value;
1156 break;
1157 case REL_Y:
1158 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1159 mAccumulator.relY = rawEvent->value;
1160 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001161 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001162 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001163
Jeff Brown6d0fec22010-07-23 21:28:06 -07001164 case EV_SYN:
1165 switch (rawEvent->scanCode) {
1166 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001167 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001168 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001169 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001170 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001171 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001172}
1173
Jeff Brown83c09682010-12-23 17:50:18 -08001174void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001175 uint32_t fields = mAccumulator.fields;
1176 if (fields == 0) {
1177 return; // no new state changes, so nothing to do
1178 }
1179
Jeff Brown6328cdc2010-07-29 18:18:33 -07001180 int motionEventAction;
1181 PointerCoords pointerCoords;
1182 nsecs_t downTime;
1183 { // acquire lock
1184 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001185
Jeff Brown6328cdc2010-07-29 18:18:33 -07001186 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1187
1188 if (downChanged) {
1189 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001190 if (!mLocked.down) {
1191 mLocked.down = true;
1192 mLocked.downTime = when;
1193 } else {
1194 downChanged = false;
1195 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001196 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001197 if (mLocked.down) {
1198 mLocked.down = false;
1199 } else {
1200 downChanged = false;
1201 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001202 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001203 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001204
Jeff Brown6328cdc2010-07-29 18:18:33 -07001205 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001206 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1207 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001208
Jeff Brown6328cdc2010-07-29 18:18:33 -07001209 if (downChanged) {
1210 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001211 } else {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001212 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001213 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001214
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001215 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001216 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001217 // Rotate motion based on display orientation if needed.
1218 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1219 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001220 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1221 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001222 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001223 }
1224
1225 float temp;
1226 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001227 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001228 temp = deltaX;
1229 deltaX = deltaY;
1230 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001231 break;
1232
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001233 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001234 deltaX = -deltaX;
1235 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001236 break;
1237
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001238 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001239 temp = deltaX;
1240 deltaX = -deltaY;
1241 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001242 break;
1243 }
1244 }
Jeff Brown83c09682010-12-23 17:50:18 -08001245
1246 if (mPointerController != NULL) {
1247 mPointerController->move(deltaX, deltaY);
1248 if (downChanged) {
1249 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1250 }
1251 mPointerController->getPosition(&pointerCoords.x, &pointerCoords.y);
1252 } else {
1253 pointerCoords.x = deltaX;
1254 pointerCoords.y = deltaY;
1255 }
1256
1257 pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
1258 pointerCoords.size = 0;
1259 pointerCoords.touchMajor = 0;
1260 pointerCoords.touchMinor = 0;
1261 pointerCoords.toolMajor = 0;
1262 pointerCoords.toolMinor = 0;
1263 pointerCoords.orientation = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001264 } // release lock
1265
Jeff Brown6d0fec22010-07-23 21:28:06 -07001266 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001267 int32_t pointerId = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001268 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
Jeff Brown85a31762010-09-01 17:01:00 -07001269 motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brownb6997262010-10-08 22:31:17 -07001270 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1271
1272 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001273}
1274
Jeff Brown83c09682010-12-23 17:50:18 -08001275int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001276 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1277 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1278 } else {
1279 return AKEY_STATE_UNKNOWN;
1280 }
1281}
1282
Jeff Brown6d0fec22010-07-23 21:28:06 -07001283
1284// --- TouchInputMapper ---
1285
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001286TouchInputMapper::TouchInputMapper(InputDevice* device) :
1287 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001288 mLocked.surfaceOrientation = -1;
1289 mLocked.surfaceWidth = -1;
1290 mLocked.surfaceHeight = -1;
1291
1292 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001293}
1294
1295TouchInputMapper::~TouchInputMapper() {
1296}
1297
1298uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001299 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001300}
1301
1302void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1303 InputMapper::populateDeviceInfo(info);
1304
Jeff Brown6328cdc2010-07-29 18:18:33 -07001305 { // acquire lock
1306 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001307
Jeff Brown6328cdc2010-07-29 18:18:33 -07001308 // Ensure surface information is up to date so that orientation changes are
1309 // noticed immediately.
1310 configureSurfaceLocked();
1311
1312 info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
1313 info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001314
1315 if (mLocked.orientedRanges.havePressure) {
1316 info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
1317 mLocked.orientedRanges.pressure);
1318 }
1319
1320 if (mLocked.orientedRanges.haveSize) {
1321 info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
1322 mLocked.orientedRanges.size);
1323 }
1324
Jeff Brownc6d282b2010-10-14 21:42:15 -07001325 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown8d608662010-08-30 03:02:23 -07001326 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
1327 mLocked.orientedRanges.touchMajor);
1328 info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
1329 mLocked.orientedRanges.touchMinor);
1330 }
1331
Jeff Brownc6d282b2010-10-14 21:42:15 -07001332 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown8d608662010-08-30 03:02:23 -07001333 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
1334 mLocked.orientedRanges.toolMajor);
1335 info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
1336 mLocked.orientedRanges.toolMinor);
1337 }
1338
1339 if (mLocked.orientedRanges.haveOrientation) {
1340 info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
1341 mLocked.orientedRanges.orientation);
1342 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001343 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001344}
1345
Jeff Brownef3d7e82010-09-30 14:33:04 -07001346void TouchInputMapper::dump(String8& dump) {
1347 { // acquire lock
1348 AutoMutex _l(mLock);
1349 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001350 dumpParameters(dump);
1351 dumpVirtualKeysLocked(dump);
1352 dumpRawAxes(dump);
1353 dumpCalibration(dump);
1354 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001355 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001356 dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
1357 dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
1358 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1359 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1360 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1361 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1362 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1363 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1364 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1365 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1366 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1367 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1368 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1369 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001370 } // release lock
1371}
1372
Jeff Brown6328cdc2010-07-29 18:18:33 -07001373void TouchInputMapper::initializeLocked() {
1374 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001375 mLastTouch.clear();
1376 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001377
1378 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1379 mAveragingTouchFilter.historyStart[i] = 0;
1380 mAveragingTouchFilter.historyEnd[i] = 0;
1381 }
1382
1383 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001384
1385 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001386
1387 mLocked.orientedRanges.havePressure = false;
1388 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001389 mLocked.orientedRanges.haveTouchSize = false;
1390 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001391 mLocked.orientedRanges.haveOrientation = false;
1392}
1393
Jeff Brown6d0fec22010-07-23 21:28:06 -07001394void TouchInputMapper::configure() {
1395 InputMapper::configure();
1396
1397 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001398 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001399
Jeff Brown83c09682010-12-23 17:50:18 -08001400 // Configure sources.
1401 switch (mParameters.deviceType) {
1402 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1403 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1404 break;
1405 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1406 mSources = AINPUT_SOURCE_TOUCHPAD;
1407 break;
1408 default:
1409 assert(false);
1410 }
1411
Jeff Brown6d0fec22010-07-23 21:28:06 -07001412 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001413 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001414
1415 // Prepare input device calibration.
1416 parseCalibration();
1417 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001418
Jeff Brown6328cdc2010-07-29 18:18:33 -07001419 { // acquire lock
1420 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001421
Jeff Brown8d608662010-08-30 03:02:23 -07001422 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001423 configureSurfaceLocked();
1424 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001425}
1426
Jeff Brown8d608662010-08-30 03:02:23 -07001427void TouchInputMapper::configureParameters() {
1428 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1429 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1430 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001431
1432 String8 deviceTypeString;
1433 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1434 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1435 deviceTypeString)) {
1436 if (deviceTypeString == "touchPad") {
1437 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1438 } else if (deviceTypeString != "touchScreen") {
1439 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1440 }
1441 }
1442 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1443
1444 mParameters.orientationAware = isTouchScreen;
1445 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1446 mParameters.orientationAware);
1447
1448 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001449}
1450
Jeff Brownef3d7e82010-09-30 14:33:04 -07001451void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001452 dump.append(INDENT3 "Parameters:\n");
1453
1454 switch (mParameters.deviceType) {
1455 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1456 dump.append(INDENT4 "DeviceType: touchScreen\n");
1457 break;
1458 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1459 dump.append(INDENT4 "DeviceType: touchPad\n");
1460 break;
1461 default:
1462 assert(false);
1463 }
1464
1465 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1466 mParameters.associatedDisplayId);
1467 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1468 toString(mParameters.orientationAware));
1469
1470 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001471 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001472 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001473 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001474 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001475 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001476}
1477
Jeff Brown8d608662010-08-30 03:02:23 -07001478void TouchInputMapper::configureRawAxes() {
1479 mRawAxes.x.clear();
1480 mRawAxes.y.clear();
1481 mRawAxes.pressure.clear();
1482 mRawAxes.touchMajor.clear();
1483 mRawAxes.touchMinor.clear();
1484 mRawAxes.toolMajor.clear();
1485 mRawAxes.toolMinor.clear();
1486 mRawAxes.orientation.clear();
1487}
1488
Jeff Brownef3d7e82010-09-30 14:33:04 -07001489static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
Jeff Brownb88102f2010-09-08 11:49:43 -07001490 if (axis.valid) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001491 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
Jeff Brownb88102f2010-09-08 11:49:43 -07001492 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1493 } else {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001494 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
Jeff Brownb88102f2010-09-08 11:49:43 -07001495 }
1496}
1497
Jeff Brownef3d7e82010-09-30 14:33:04 -07001498void TouchInputMapper::dumpRawAxes(String8& dump) {
1499 dump.append(INDENT3 "Raw Axes:\n");
1500 dumpAxisInfo(dump, mRawAxes.x, "X");
1501 dumpAxisInfo(dump, mRawAxes.y, "Y");
1502 dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
1503 dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1504 dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1505 dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1506 dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1507 dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001508}
1509
Jeff Brown6328cdc2010-07-29 18:18:33 -07001510bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001511 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001512 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001513 int32_t width = mRawAxes.x.getRange();
1514 int32_t height = mRawAxes.y.getRange();
1515
1516 if (mParameters.associatedDisplayId >= 0) {
1517 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1518 bool wantOrientation = mParameters.orientationAware;
1519
Jeff Brown6328cdc2010-07-29 18:18:33 -07001520 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001521 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1522 wantSize ? &width : NULL, wantSize ? &height : NULL,
1523 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001524 return false;
1525 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001526 }
1527
Jeff Brown6328cdc2010-07-29 18:18:33 -07001528 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001529 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001530 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001531 }
1532
Jeff Brown6328cdc2010-07-29 18:18:33 -07001533 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001534 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001535 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001536 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001537
Jeff Brown6328cdc2010-07-29 18:18:33 -07001538 mLocked.surfaceWidth = width;
1539 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001540
Jeff Brown8d608662010-08-30 03:02:23 -07001541 // Configure X and Y factors.
1542 if (mRawAxes.x.valid && mRawAxes.y.valid) {
Jeff Brown511ee5f2010-10-18 13:32:20 -07001543 mLocked.xOrigin = mCalibration.haveXOrigin
1544 ? mCalibration.xOrigin
1545 : mRawAxes.x.minValue;
1546 mLocked.yOrigin = mCalibration.haveYOrigin
1547 ? mCalibration.yOrigin
1548 : mRawAxes.y.minValue;
1549 mLocked.xScale = mCalibration.haveXScale
1550 ? mCalibration.xScale
1551 : float(width) / mRawAxes.x.getRange();
1552 mLocked.yScale = mCalibration.haveYScale
1553 ? mCalibration.yScale
1554 : float(height) / mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001555 mLocked.xPrecision = 1.0f / mLocked.xScale;
1556 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001557
Jeff Brown6328cdc2010-07-29 18:18:33 -07001558 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001559 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07001560 LOGW(INDENT "Touch device did not report support for X or Y axis!");
Jeff Brown6328cdc2010-07-29 18:18:33 -07001561 mLocked.xOrigin = 0;
1562 mLocked.yOrigin = 0;
1563 mLocked.xScale = 1.0f;
1564 mLocked.yScale = 1.0f;
1565 mLocked.xPrecision = 1.0f;
1566 mLocked.yPrecision = 1.0f;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001567 }
1568
Jeff Brown8d608662010-08-30 03:02:23 -07001569 // Scale factor for terms that are not oriented in a particular axis.
1570 // If the pixels are square then xScale == yScale otherwise we fake it
1571 // by choosing an average.
1572 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001573
Jeff Brown8d608662010-08-30 03:02:23 -07001574 // Size of diagonal axis.
1575 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001576
Jeff Brown8d608662010-08-30 03:02:23 -07001577 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001578 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1579 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001580 mLocked.orientedRanges.touchMajor.min = 0;
1581 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1582 mLocked.orientedRanges.touchMajor.flat = 0;
1583 mLocked.orientedRanges.touchMajor.fuzz = 0;
1584 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1585 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001586
Jeff Brown8d608662010-08-30 03:02:23 -07001587 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001588 mLocked.toolSizeLinearScale = 0;
1589 mLocked.toolSizeLinearBias = 0;
1590 mLocked.toolSizeAreaScale = 0;
1591 mLocked.toolSizeAreaBias = 0;
1592 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1593 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1594 if (mCalibration.haveToolSizeLinearScale) {
1595 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001596 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001597 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001598 / mRawAxes.toolMajor.maxValue;
1599 }
1600
Jeff Brownc6d282b2010-10-14 21:42:15 -07001601 if (mCalibration.haveToolSizeLinearBias) {
1602 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1603 }
1604 } else if (mCalibration.toolSizeCalibration ==
1605 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1606 if (mCalibration.haveToolSizeLinearScale) {
1607 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1608 } else {
1609 mLocked.toolSizeLinearScale = min(width, height);
1610 }
1611
1612 if (mCalibration.haveToolSizeLinearBias) {
1613 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1614 }
1615
1616 if (mCalibration.haveToolSizeAreaScale) {
1617 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1618 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1619 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1620 }
1621
1622 if (mCalibration.haveToolSizeAreaBias) {
1623 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001624 }
1625 }
1626
Jeff Brownc6d282b2010-10-14 21:42:15 -07001627 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001628 mLocked.orientedRanges.toolMajor.min = 0;
1629 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1630 mLocked.orientedRanges.toolMajor.flat = 0;
1631 mLocked.orientedRanges.toolMajor.fuzz = 0;
1632 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1633 }
1634
1635 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001636 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001637 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1638 RawAbsoluteAxisInfo rawPressureAxis;
1639 switch (mCalibration.pressureSource) {
1640 case Calibration::PRESSURE_SOURCE_PRESSURE:
1641 rawPressureAxis = mRawAxes.pressure;
1642 break;
1643 case Calibration::PRESSURE_SOURCE_TOUCH:
1644 rawPressureAxis = mRawAxes.touchMajor;
1645 break;
1646 default:
1647 rawPressureAxis.clear();
1648 }
1649
Jeff Brown8d608662010-08-30 03:02:23 -07001650 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1651 || mCalibration.pressureCalibration
1652 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1653 if (mCalibration.havePressureScale) {
1654 mLocked.pressureScale = mCalibration.pressureScale;
1655 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1656 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1657 }
1658 }
1659
1660 mLocked.orientedRanges.havePressure = true;
1661 mLocked.orientedRanges.pressure.min = 0;
1662 mLocked.orientedRanges.pressure.max = 1.0;
1663 mLocked.orientedRanges.pressure.flat = 0;
1664 mLocked.orientedRanges.pressure.fuzz = 0;
1665 }
1666
1667 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001668 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001669 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001670 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1671 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1672 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1673 }
1674 }
1675
1676 mLocked.orientedRanges.haveSize = true;
1677 mLocked.orientedRanges.size.min = 0;
1678 mLocked.orientedRanges.size.max = 1.0;
1679 mLocked.orientedRanges.size.flat = 0;
1680 mLocked.orientedRanges.size.fuzz = 0;
1681 }
1682
1683 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001684 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001685 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001686 if (mCalibration.orientationCalibration
1687 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1688 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1689 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1690 }
1691 }
1692
1693 mLocked.orientedRanges.orientation.min = - M_PI_2;
1694 mLocked.orientedRanges.orientation.max = M_PI_2;
1695 mLocked.orientedRanges.orientation.flat = 0;
1696 mLocked.orientedRanges.orientation.fuzz = 0;
1697 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001698 }
1699
1700 if (orientationChanged || sizeChanged) {
1701 // Compute oriented surface dimensions, precision, and scales.
1702 float orientedXScale, orientedYScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001703 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001704 case DISPLAY_ORIENTATION_90:
1705 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001706 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1707 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
1708 mLocked.orientedXPrecision = mLocked.yPrecision;
1709 mLocked.orientedYPrecision = mLocked.xPrecision;
1710 orientedXScale = mLocked.yScale;
1711 orientedYScale = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001712 break;
1713 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001714 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1715 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
1716 mLocked.orientedXPrecision = mLocked.xPrecision;
1717 mLocked.orientedYPrecision = mLocked.yPrecision;
1718 orientedXScale = mLocked.xScale;
1719 orientedYScale = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001720 break;
1721 }
1722
1723 // Configure position ranges.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001724 mLocked.orientedRanges.x.min = 0;
1725 mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
1726 mLocked.orientedRanges.x.flat = 0;
1727 mLocked.orientedRanges.x.fuzz = orientedXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001728
Jeff Brown6328cdc2010-07-29 18:18:33 -07001729 mLocked.orientedRanges.y.min = 0;
1730 mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
1731 mLocked.orientedRanges.y.flat = 0;
1732 mLocked.orientedRanges.y.fuzz = orientedYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001733 }
1734
1735 return true;
1736}
1737
Jeff Brownef3d7e82010-09-30 14:33:04 -07001738void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1739 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1740 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1741 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001742}
1743
Jeff Brown6328cdc2010-07-29 18:18:33 -07001744void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001745 assert(mRawAxes.x.valid && mRawAxes.y.valid);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001746
Jeff Brown8d608662010-08-30 03:02:23 -07001747 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001748 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001749
Jeff Brown6328cdc2010-07-29 18:18:33 -07001750 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001751
Jeff Brown6328cdc2010-07-29 18:18:33 -07001752 if (virtualKeyDefinitions.size() == 0) {
1753 return;
1754 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001755
Jeff Brown6328cdc2010-07-29 18:18:33 -07001756 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1757
Jeff Brown8d608662010-08-30 03:02:23 -07001758 int32_t touchScreenLeft = mRawAxes.x.minValue;
1759 int32_t touchScreenTop = mRawAxes.y.minValue;
1760 int32_t touchScreenWidth = mRawAxes.x.getRange();
1761 int32_t touchScreenHeight = mRawAxes.y.getRange();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001762
1763 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001764 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001765 virtualKeyDefinitions[i];
1766
1767 mLocked.virtualKeys.add();
1768 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1769
1770 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1771 int32_t keyCode;
1772 uint32_t flags;
1773 if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
1774 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001775 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1776 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001777 mLocked.virtualKeys.pop(); // drop the key
1778 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001779 }
1780
Jeff Brown6328cdc2010-07-29 18:18:33 -07001781 virtualKey.keyCode = keyCode;
1782 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001783
Jeff Brown6328cdc2010-07-29 18:18:33 -07001784 // convert the key definition's display coordinates into touch coordinates for a hit box
1785 int32_t halfWidth = virtualKeyDefinition.width / 2;
1786 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001787
Jeff Brown6328cdc2010-07-29 18:18:33 -07001788 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1789 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1790 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1791 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1792 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1793 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1794 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1795 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001796
Jeff Brownef3d7e82010-09-30 14:33:04 -07001797 }
1798}
1799
1800void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1801 if (!mLocked.virtualKeys.isEmpty()) {
1802 dump.append(INDENT3 "Virtual Keys:\n");
1803
1804 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1805 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1806 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1807 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1808 i, virtualKey.scanCode, virtualKey.keyCode,
1809 virtualKey.hitLeft, virtualKey.hitRight,
1810 virtualKey.hitTop, virtualKey.hitBottom);
1811 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001812 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001813}
1814
Jeff Brown8d608662010-08-30 03:02:23 -07001815void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001816 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07001817 Calibration& out = mCalibration;
1818
Jeff Brown511ee5f2010-10-18 13:32:20 -07001819 // Position
1820 out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
1821 out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
1822 out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
1823 out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
1824
Jeff Brownc6d282b2010-10-14 21:42:15 -07001825 // Touch Size
1826 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
1827 String8 touchSizeCalibrationString;
1828 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
1829 if (touchSizeCalibrationString == "none") {
1830 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
1831 } else if (touchSizeCalibrationString == "geometric") {
1832 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
1833 } else if (touchSizeCalibrationString == "pressure") {
1834 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
1835 } else if (touchSizeCalibrationString != "default") {
1836 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
1837 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001838 }
1839 }
1840
Jeff Brownc6d282b2010-10-14 21:42:15 -07001841 // Tool Size
1842 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
1843 String8 toolSizeCalibrationString;
1844 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
1845 if (toolSizeCalibrationString == "none") {
1846 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
1847 } else if (toolSizeCalibrationString == "geometric") {
1848 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
1849 } else if (toolSizeCalibrationString == "linear") {
1850 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
1851 } else if (toolSizeCalibrationString == "area") {
1852 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
1853 } else if (toolSizeCalibrationString != "default") {
1854 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
1855 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07001856 }
1857 }
1858
Jeff Brownc6d282b2010-10-14 21:42:15 -07001859 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
1860 out.toolSizeLinearScale);
1861 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
1862 out.toolSizeLinearBias);
1863 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
1864 out.toolSizeAreaScale);
1865 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
1866 out.toolSizeAreaBias);
1867 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
1868 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07001869
1870 // Pressure
1871 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
1872 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001873 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001874 if (pressureCalibrationString == "none") {
1875 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1876 } else if (pressureCalibrationString == "physical") {
1877 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
1878 } else if (pressureCalibrationString == "amplitude") {
1879 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1880 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001881 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001882 pressureCalibrationString.string());
1883 }
1884 }
1885
1886 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
1887 String8 pressureSourceString;
1888 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
1889 if (pressureSourceString == "pressure") {
1890 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1891 } else if (pressureSourceString == "touch") {
1892 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1893 } else if (pressureSourceString != "default") {
1894 LOGW("Invalid value for touch.pressure.source: '%s'",
1895 pressureSourceString.string());
1896 }
1897 }
1898
1899 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
1900 out.pressureScale);
1901
1902 // Size
1903 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
1904 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001905 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001906 if (sizeCalibrationString == "none") {
1907 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
1908 } else if (sizeCalibrationString == "normalized") {
1909 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
1910 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001911 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001912 sizeCalibrationString.string());
1913 }
1914 }
1915
1916 // Orientation
1917 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
1918 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001919 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001920 if (orientationCalibrationString == "none") {
1921 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
1922 } else if (orientationCalibrationString == "interpolated") {
1923 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08001924 } else if (orientationCalibrationString == "vector") {
1925 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001926 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001927 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07001928 orientationCalibrationString.string());
1929 }
1930 }
1931}
1932
1933void TouchInputMapper::resolveCalibration() {
1934 // Pressure
1935 switch (mCalibration.pressureSource) {
1936 case Calibration::PRESSURE_SOURCE_DEFAULT:
1937 if (mRawAxes.pressure.valid) {
1938 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
1939 } else if (mRawAxes.touchMajor.valid) {
1940 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
1941 }
1942 break;
1943
1944 case Calibration::PRESSURE_SOURCE_PRESSURE:
1945 if (! mRawAxes.pressure.valid) {
1946 LOGW("Calibration property touch.pressure.source is 'pressure' but "
1947 "the pressure axis is not available.");
1948 }
1949 break;
1950
1951 case Calibration::PRESSURE_SOURCE_TOUCH:
1952 if (! mRawAxes.touchMajor.valid) {
1953 LOGW("Calibration property touch.pressure.source is 'touch' but "
1954 "the touchMajor axis is not available.");
1955 }
1956 break;
1957
1958 default:
1959 break;
1960 }
1961
1962 switch (mCalibration.pressureCalibration) {
1963 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
1964 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
1965 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
1966 } else {
1967 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
1968 }
1969 break;
1970
1971 default:
1972 break;
1973 }
1974
Jeff Brownc6d282b2010-10-14 21:42:15 -07001975 // Tool Size
1976 switch (mCalibration.toolSizeCalibration) {
1977 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07001978 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001979 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07001980 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001981 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07001982 }
1983 break;
1984
1985 default:
1986 break;
1987 }
1988
Jeff Brownc6d282b2010-10-14 21:42:15 -07001989 // Touch Size
1990 switch (mCalibration.touchSizeCalibration) {
1991 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07001992 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07001993 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1994 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07001995 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001996 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07001997 }
1998 break;
1999
2000 default:
2001 break;
2002 }
2003
2004 // Size
2005 switch (mCalibration.sizeCalibration) {
2006 case Calibration::SIZE_CALIBRATION_DEFAULT:
2007 if (mRawAxes.toolMajor.valid) {
2008 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2009 } else {
2010 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2011 }
2012 break;
2013
2014 default:
2015 break;
2016 }
2017
2018 // Orientation
2019 switch (mCalibration.orientationCalibration) {
2020 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2021 if (mRawAxes.orientation.valid) {
2022 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2023 } else {
2024 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2025 }
2026 break;
2027
2028 default:
2029 break;
2030 }
2031}
2032
Jeff Brownef3d7e82010-09-30 14:33:04 -07002033void TouchInputMapper::dumpCalibration(String8& dump) {
2034 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002035
Jeff Brown511ee5f2010-10-18 13:32:20 -07002036 // Position
2037 if (mCalibration.haveXOrigin) {
2038 dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
2039 }
2040 if (mCalibration.haveYOrigin) {
2041 dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
2042 }
2043 if (mCalibration.haveXScale) {
2044 dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
2045 }
2046 if (mCalibration.haveYScale) {
2047 dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
2048 }
2049
Jeff Brownc6d282b2010-10-14 21:42:15 -07002050 // Touch Size
2051 switch (mCalibration.touchSizeCalibration) {
2052 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2053 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002054 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002055 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2056 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002057 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002058 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2059 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002060 break;
2061 default:
2062 assert(false);
2063 }
2064
Jeff Brownc6d282b2010-10-14 21:42:15 -07002065 // Tool Size
2066 switch (mCalibration.toolSizeCalibration) {
2067 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2068 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002069 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002070 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2071 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002072 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002073 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2074 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2075 break;
2076 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2077 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002078 break;
2079 default:
2080 assert(false);
2081 }
2082
Jeff Brownc6d282b2010-10-14 21:42:15 -07002083 if (mCalibration.haveToolSizeLinearScale) {
2084 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2085 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002086 }
2087
Jeff Brownc6d282b2010-10-14 21:42:15 -07002088 if (mCalibration.haveToolSizeLinearBias) {
2089 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2090 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002091 }
2092
Jeff Brownc6d282b2010-10-14 21:42:15 -07002093 if (mCalibration.haveToolSizeAreaScale) {
2094 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2095 mCalibration.toolSizeAreaScale);
2096 }
2097
2098 if (mCalibration.haveToolSizeAreaBias) {
2099 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2100 mCalibration.toolSizeAreaBias);
2101 }
2102
2103 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002104 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002105 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002106 }
2107
2108 // Pressure
2109 switch (mCalibration.pressureCalibration) {
2110 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002111 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002112 break;
2113 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002114 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002115 break;
2116 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002117 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002118 break;
2119 default:
2120 assert(false);
2121 }
2122
2123 switch (mCalibration.pressureSource) {
2124 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002125 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002126 break;
2127 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002128 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002129 break;
2130 case Calibration::PRESSURE_SOURCE_DEFAULT:
2131 break;
2132 default:
2133 assert(false);
2134 }
2135
2136 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002137 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2138 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002139 }
2140
2141 // Size
2142 switch (mCalibration.sizeCalibration) {
2143 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002144 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002145 break;
2146 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002147 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002148 break;
2149 default:
2150 assert(false);
2151 }
2152
2153 // Orientation
2154 switch (mCalibration.orientationCalibration) {
2155 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002156 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002157 break;
2158 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002159 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002160 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002161 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2162 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2163 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002164 default:
2165 assert(false);
2166 }
2167}
2168
Jeff Brown6d0fec22010-07-23 21:28:06 -07002169void TouchInputMapper::reset() {
2170 // Synthesize touch up event if touch is currently down.
2171 // This will also take care of finishing virtual key processing if needed.
2172 if (mLastTouch.pointerCount != 0) {
2173 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2174 mCurrentTouch.clear();
2175 syncTouch(when, true);
2176 }
2177
Jeff Brown6328cdc2010-07-29 18:18:33 -07002178 { // acquire lock
2179 AutoMutex _l(mLock);
2180 initializeLocked();
2181 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002182
Jeff Brown6328cdc2010-07-29 18:18:33 -07002183 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002184}
2185
2186void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002187 uint32_t policyFlags = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002188
Jeff Brown6328cdc2010-07-29 18:18:33 -07002189 // Preprocess pointer data.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002190
Jeff Brown6d0fec22010-07-23 21:28:06 -07002191 if (mParameters.useBadTouchFilter) {
2192 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002193 havePointerIds = false;
2194 }
2195 }
2196
Jeff Brown6d0fec22010-07-23 21:28:06 -07002197 if (mParameters.useJumpyTouchFilter) {
2198 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002199 havePointerIds = false;
2200 }
2201 }
2202
2203 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002204 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002205 }
2206
Jeff Brown6d0fec22010-07-23 21:28:06 -07002207 TouchData temp;
2208 TouchData* savedTouch;
2209 if (mParameters.useAveragingTouchFilter) {
2210 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002211 savedTouch = & temp;
2212
Jeff Brown6d0fec22010-07-23 21:28:06 -07002213 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002214 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002215 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002216 }
2217
Jeff Brown6328cdc2010-07-29 18:18:33 -07002218 // Process touches and virtual keys.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002219
Jeff Brown6d0fec22010-07-23 21:28:06 -07002220 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2221 if (touchResult == DISPATCH_TOUCH) {
2222 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002223 }
2224
Jeff Brown6328cdc2010-07-29 18:18:33 -07002225 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002226
Jeff Brown6d0fec22010-07-23 21:28:06 -07002227 if (touchResult == DROP_STROKE) {
2228 mLastTouch.clear();
2229 } else {
2230 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002231 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002232}
2233
Jeff Brown6d0fec22010-07-23 21:28:06 -07002234TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2235 nsecs_t when, uint32_t policyFlags) {
2236 int32_t keyEventAction, keyEventFlags;
2237 int32_t keyCode, scanCode, downTime;
2238 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002239
Jeff Brown6328cdc2010-07-29 18:18:33 -07002240 { // acquire lock
2241 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002242
Jeff Brown6328cdc2010-07-29 18:18:33 -07002243 // Update surface size and orientation, including virtual key positions.
2244 if (! configureSurfaceLocked()) {
2245 return DROP_STROKE;
2246 }
2247
2248 // Check for virtual key press.
2249 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002250 if (mCurrentTouch.pointerCount == 0) {
2251 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002252 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002253#if DEBUG_VIRTUAL_KEYS
2254 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002255 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002256#endif
2257 keyEventAction = AKEY_EVENT_ACTION_UP;
2258 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2259 touchResult = SKIP_TOUCH;
2260 goto DispatchVirtualKey;
2261 }
2262
2263 if (mCurrentTouch.pointerCount == 1) {
2264 int32_t x = mCurrentTouch.pointers[0].x;
2265 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002266 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2267 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002268 // Pointer is still within the space of the virtual key.
2269 return SKIP_TOUCH;
2270 }
2271 }
2272
2273 // Pointer left virtual key area or another pointer also went down.
2274 // Send key cancellation and drop the stroke so subsequent motions will be
2275 // considered fresh downs. This is useful when the user swipes away from the
2276 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002277 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002278#if DEBUG_VIRTUAL_KEYS
2279 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002280 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002281#endif
2282 keyEventAction = AKEY_EVENT_ACTION_UP;
2283 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2284 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002285
2286 // Check whether the pointer moved inside the display area where we should
2287 // start a new stroke.
2288 int32_t x = mCurrentTouch.pointers[0].x;
2289 int32_t y = mCurrentTouch.pointers[0].y;
2290 if (isPointInsideSurfaceLocked(x, y)) {
2291 mLastTouch.clear();
2292 touchResult = DISPATCH_TOUCH;
2293 } else {
2294 touchResult = DROP_STROKE;
2295 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002296 } else {
2297 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2298 // Pointer just went down. Handle off-screen touches, if needed.
2299 int32_t x = mCurrentTouch.pointers[0].x;
2300 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002301 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002302 // If exactly one pointer went down, check for virtual key hit.
2303 // Otherwise we will drop the entire stroke.
2304 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002305 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002306 if (virtualKey) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002307 mLocked.currentVirtualKey.down = true;
2308 mLocked.currentVirtualKey.downTime = when;
2309 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2310 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002311#if DEBUG_VIRTUAL_KEYS
2312 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002313 mLocked.currentVirtualKey.keyCode,
2314 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002315#endif
2316 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2317 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2318 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2319 touchResult = SKIP_TOUCH;
2320 goto DispatchVirtualKey;
2321 }
2322 }
2323 return DROP_STROKE;
2324 }
2325 }
2326 return DISPATCH_TOUCH;
2327 }
2328
2329 DispatchVirtualKey:
2330 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002331 keyCode = mLocked.currentVirtualKey.keyCode;
2332 scanCode = mLocked.currentVirtualKey.scanCode;
2333 downTime = mLocked.currentVirtualKey.downTime;
2334 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002335
2336 // Dispatch virtual key.
2337 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002338 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002339 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2340 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2341 return touchResult;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002342}
2343
Jeff Brown6d0fec22010-07-23 21:28:06 -07002344void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2345 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2346 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002347 if (currentPointerCount == 0 && lastPointerCount == 0) {
2348 return; // nothing to do!
2349 }
2350
Jeff Brown6d0fec22010-07-23 21:28:06 -07002351 BitSet32 currentIdBits = mCurrentTouch.idBits;
2352 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002353
2354 if (currentIdBits == lastIdBits) {
2355 // No pointer id changes so this is a move event.
2356 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002357 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002358 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002359 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002360 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002361 // There may be pointers going up and pointers going down and pointers moving
2362 // all at the same time.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002363 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2364 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2365 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002366 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002367
Jeff Brownc3db8582010-10-20 15:33:38 -07002368 // Produce an intermediate representation of the touch data that consists of the
2369 // old location of pointers that have just gone up and the new location of pointers that
2370 // have just moved but omits the location of pointers that have just gone down.
2371 TouchData interimTouch;
2372 interimTouch.copyFrom(mLastTouch);
2373
2374 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2375 bool moveNeeded = false;
2376 while (!moveIdBits.isEmpty()) {
2377 uint32_t moveId = moveIdBits.firstMarkedBit();
2378 moveIdBits.clearBit(moveId);
2379
2380 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2381 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2382 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2383 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2384 moveNeeded = true;
2385 }
2386 }
2387
2388 // Dispatch pointer up events using the interim pointer locations.
2389 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002390 uint32_t upId = upIdBits.firstMarkedBit();
2391 upIdBits.clearBit(upId);
2392 BitSet32 oldActiveIdBits = activeIdBits;
2393 activeIdBits.clearBit(upId);
2394
2395 int32_t motionEventAction;
2396 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002397 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002398 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002399 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002400 }
2401
Jeff Brownc3db8582010-10-20 15:33:38 -07002402 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002403 oldActiveIdBits, upId, pointerCount, motionEventAction);
2404 pointerCount -= 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002405 }
2406
Jeff Brownc3db8582010-10-20 15:33:38 -07002407 // Dispatch move events if any of the remaining pointers moved from their old locations.
2408 // Although applications receive new locations as part of individual pointer up
2409 // events, they do not generally handle them except when presented in a move event.
2410 if (moveNeeded) {
2411 dispatchTouch(when, policyFlags, &mCurrentTouch,
2412 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2413 }
2414
2415 // Dispatch pointer down events using the new pointer locations.
2416 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002417 uint32_t downId = downIdBits.firstMarkedBit();
2418 downIdBits.clearBit(downId);
2419 BitSet32 oldActiveIdBits = activeIdBits;
2420 activeIdBits.markBit(downId);
2421
2422 int32_t motionEventAction;
2423 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002424 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002425 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002426 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002427 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002428 }
2429
Jeff Brown8d608662010-08-30 03:02:23 -07002430 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002431 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002432 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002433 }
2434 }
2435}
2436
Jeff Brown6d0fec22010-07-23 21:28:06 -07002437void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002438 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002439 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002440 int32_t pointerIds[MAX_POINTERS];
2441 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown46b9ac02010-04-22 18:58:52 -07002442 int32_t motionEventEdgeFlags = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002443 float xPrecision, yPrecision;
2444
2445 { // acquire lock
2446 AutoMutex _l(mLock);
2447
2448 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2449 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002450 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002451 uint32_t id = idBits.firstMarkedBit();
2452 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002453 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002454
Jeff Brown8d608662010-08-30 03:02:23 -07002455 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002456
Jeff Brown8d608662010-08-30 03:02:23 -07002457 // X and Y
2458 float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
2459 float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002460
Jeff Brown8d608662010-08-30 03:02:23 -07002461 // ToolMajor and ToolMinor
2462 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002463 switch (mCalibration.toolSizeCalibration) {
2464 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002465 toolMajor = in.toolMajor * mLocked.geometricScale;
2466 if (mRawAxes.toolMinor.valid) {
2467 toolMinor = in.toolMinor * mLocked.geometricScale;
2468 } else {
2469 toolMinor = toolMajor;
2470 }
2471 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002472 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002473 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002474 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002475 : 0;
2476 if (mRawAxes.toolMinor.valid) {
2477 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002478 ? in.toolMinor * mLocked.toolSizeLinearScale
2479 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002480 : 0;
2481 } else {
2482 toolMinor = toolMajor;
2483 }
2484 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002485 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2486 if (in.toolMajor != 0) {
2487 float diameter = sqrtf(in.toolMajor
2488 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2489 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2490 } else {
2491 toolMajor = 0;
2492 }
2493 toolMinor = toolMajor;
2494 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002495 default:
2496 toolMajor = 0;
2497 toolMinor = 0;
2498 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002499 }
2500
Jeff Brownc6d282b2010-10-14 21:42:15 -07002501 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002502 toolMajor /= pointerCount;
2503 toolMinor /= pointerCount;
2504 }
2505
2506 // Pressure
2507 float rawPressure;
2508 switch (mCalibration.pressureSource) {
2509 case Calibration::PRESSURE_SOURCE_PRESSURE:
2510 rawPressure = in.pressure;
2511 break;
2512 case Calibration::PRESSURE_SOURCE_TOUCH:
2513 rawPressure = in.touchMajor;
2514 break;
2515 default:
2516 rawPressure = 0;
2517 }
2518
2519 float pressure;
2520 switch (mCalibration.pressureCalibration) {
2521 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2522 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2523 pressure = rawPressure * mLocked.pressureScale;
2524 break;
2525 default:
2526 pressure = 1;
2527 break;
2528 }
2529
2530 // TouchMajor and TouchMinor
2531 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002532 switch (mCalibration.touchSizeCalibration) {
2533 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002534 touchMajor = in.touchMajor * mLocked.geometricScale;
2535 if (mRawAxes.touchMinor.valid) {
2536 touchMinor = in.touchMinor * mLocked.geometricScale;
2537 } else {
2538 touchMinor = touchMajor;
2539 }
2540 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002541 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002542 touchMajor = toolMajor * pressure;
2543 touchMinor = toolMinor * pressure;
2544 break;
2545 default:
2546 touchMajor = 0;
2547 touchMinor = 0;
2548 break;
2549 }
2550
2551 if (touchMajor > toolMajor) {
2552 touchMajor = toolMajor;
2553 }
2554 if (touchMinor > toolMinor) {
2555 touchMinor = toolMinor;
2556 }
2557
2558 // Size
2559 float size;
2560 switch (mCalibration.sizeCalibration) {
2561 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2562 float rawSize = mRawAxes.toolMinor.valid
2563 ? avg(in.toolMajor, in.toolMinor)
2564 : in.toolMajor;
2565 size = rawSize * mLocked.sizeScale;
2566 break;
2567 }
2568 default:
2569 size = 0;
2570 break;
2571 }
2572
2573 // Orientation
2574 float orientation;
2575 switch (mCalibration.orientationCalibration) {
2576 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2577 orientation = in.orientation * mLocked.orientationScale;
2578 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002579 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2580 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2581 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2582 if (c1 != 0 || c2 != 0) {
2583 orientation = atan2f(c1, c2) * 0.5f;
2584 float minorAxisScale = (16.0f - pythag(c1, c2)) / 16.0f;
2585 toolMinor *= minorAxisScale;
2586 touchMinor *= minorAxisScale;
2587 } else {
2588 orientation = 0;
2589 }
2590 break;
2591 }
Jeff Brown8d608662010-08-30 03:02:23 -07002592 default:
2593 orientation = 0;
2594 }
2595
2596 // Adjust coords for orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002597 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002598 case DISPLAY_ORIENTATION_90: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002599 float xTemp = x;
2600 x = y;
2601 y = mLocked.surfaceWidth - xTemp;
2602 orientation -= M_PI_2;
2603 if (orientation < - M_PI_2) {
2604 orientation += M_PI;
2605 }
2606 break;
2607 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002608 case DISPLAY_ORIENTATION_180: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002609 x = mLocked.surfaceWidth - x;
2610 y = mLocked.surfaceHeight - y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002611 break;
2612 }
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002613 case DISPLAY_ORIENTATION_270: {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002614 float xTemp = x;
2615 x = mLocked.surfaceHeight - y;
2616 y = xTemp;
2617 orientation += M_PI_2;
2618 if (orientation > M_PI_2) {
2619 orientation -= M_PI;
2620 }
2621 break;
2622 }
2623 }
2624
Jeff Brown8d608662010-08-30 03:02:23 -07002625 // Write output coords.
2626 PointerCoords& out = pointerCoords[outIndex];
2627 out.x = x;
2628 out.y = y;
2629 out.pressure = pressure;
2630 out.size = size;
2631 out.touchMajor = touchMajor;
2632 out.touchMinor = touchMinor;
2633 out.toolMajor = toolMajor;
2634 out.toolMinor = toolMinor;
2635 out.orientation = orientation;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002636
Jeff Brown8d608662010-08-30 03:02:23 -07002637 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002638
2639 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002640 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002641 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002642 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002643
2644 // Check edge flags by looking only at the first pointer since the flags are
2645 // global to the event.
2646 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
2647 if (pointerCoords[0].x <= 0) {
2648 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
2649 } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
2650 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
2651 }
2652 if (pointerCoords[0].y <= 0) {
2653 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
2654 } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
2655 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
2656 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002657 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002658
2659 xPrecision = mLocked.orientedXPrecision;
2660 yPrecision = mLocked.orientedYPrecision;
2661 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07002662
Jeff Brown83c09682010-12-23 17:50:18 -08002663 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002664 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002665 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002666 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002667}
2668
Jeff Brown6328cdc2010-07-29 18:18:33 -07002669bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown8d608662010-08-30 03:02:23 -07002670 if (mRawAxes.x.valid && mRawAxes.y.valid) {
2671 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2672 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002673 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002674 return true;
2675}
2676
Jeff Brown6328cdc2010-07-29 18:18:33 -07002677const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2678 int32_t x, int32_t y) {
2679 size_t numVirtualKeys = mLocked.virtualKeys.size();
2680 for (size_t i = 0; i < numVirtualKeys; i++) {
2681 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002682
2683#if DEBUG_VIRTUAL_KEYS
2684 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2685 "left=%d, top=%d, right=%d, bottom=%d",
2686 x, y,
2687 virtualKey.keyCode, virtualKey.scanCode,
2688 virtualKey.hitLeft, virtualKey.hitTop,
2689 virtualKey.hitRight, virtualKey.hitBottom);
2690#endif
2691
2692 if (virtualKey.isHit(x, y)) {
2693 return & virtualKey;
2694 }
2695 }
2696
2697 return NULL;
2698}
2699
2700void TouchInputMapper::calculatePointerIds() {
2701 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2702 uint32_t lastPointerCount = mLastTouch.pointerCount;
2703
2704 if (currentPointerCount == 0) {
2705 // No pointers to assign.
2706 mCurrentTouch.idBits.clear();
2707 } else if (lastPointerCount == 0) {
2708 // All pointers are new.
2709 mCurrentTouch.idBits.clear();
2710 for (uint32_t i = 0; i < currentPointerCount; i++) {
2711 mCurrentTouch.pointers[i].id = i;
2712 mCurrentTouch.idToIndex[i] = i;
2713 mCurrentTouch.idBits.markBit(i);
2714 }
2715 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2716 // Only one pointer and no change in count so it must have the same id as before.
2717 uint32_t id = mLastTouch.pointers[0].id;
2718 mCurrentTouch.pointers[0].id = id;
2719 mCurrentTouch.idToIndex[id] = 0;
2720 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2721 } else {
2722 // General case.
2723 // We build a heap of squared euclidean distances between current and last pointers
2724 // associated with the current and last pointer indices. Then, we find the best
2725 // match (by distance) for each current pointer.
2726 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2727
2728 uint32_t heapSize = 0;
2729 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2730 currentPointerIndex++) {
2731 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2732 lastPointerIndex++) {
2733 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2734 - mLastTouch.pointers[lastPointerIndex].x;
2735 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2736 - mLastTouch.pointers[lastPointerIndex].y;
2737
2738 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2739
2740 // Insert new element into the heap (sift up).
2741 heap[heapSize].currentPointerIndex = currentPointerIndex;
2742 heap[heapSize].lastPointerIndex = lastPointerIndex;
2743 heap[heapSize].distance = distance;
2744 heapSize += 1;
2745 }
2746 }
2747
2748 // Heapify
2749 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2750 startIndex -= 1;
2751 for (uint32_t parentIndex = startIndex; ;) {
2752 uint32_t childIndex = parentIndex * 2 + 1;
2753 if (childIndex >= heapSize) {
2754 break;
2755 }
2756
2757 if (childIndex + 1 < heapSize
2758 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2759 childIndex += 1;
2760 }
2761
2762 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2763 break;
2764 }
2765
2766 swap(heap[parentIndex], heap[childIndex]);
2767 parentIndex = childIndex;
2768 }
2769 }
2770
2771#if DEBUG_POINTER_ASSIGNMENT
2772 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2773 for (size_t i = 0; i < heapSize; i++) {
2774 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2775 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2776 heap[i].distance);
2777 }
2778#endif
2779
2780 // Pull matches out by increasing order of distance.
2781 // To avoid reassigning pointers that have already been matched, the loop keeps track
2782 // of which last and current pointers have been matched using the matchedXXXBits variables.
2783 // It also tracks the used pointer id bits.
2784 BitSet32 matchedLastBits(0);
2785 BitSet32 matchedCurrentBits(0);
2786 BitSet32 usedIdBits(0);
2787 bool first = true;
2788 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2789 for (;;) {
2790 if (first) {
2791 // The first time through the loop, we just consume the root element of
2792 // the heap (the one with smallest distance).
2793 first = false;
2794 } else {
2795 // Previous iterations consumed the root element of the heap.
2796 // Pop root element off of the heap (sift down).
2797 heapSize -= 1;
2798 assert(heapSize > 0);
2799
2800 // Sift down.
2801 heap[0] = heap[heapSize];
2802 for (uint32_t parentIndex = 0; ;) {
2803 uint32_t childIndex = parentIndex * 2 + 1;
2804 if (childIndex >= heapSize) {
2805 break;
2806 }
2807
2808 if (childIndex + 1 < heapSize
2809 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2810 childIndex += 1;
2811 }
2812
2813 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2814 break;
2815 }
2816
2817 swap(heap[parentIndex], heap[childIndex]);
2818 parentIndex = childIndex;
2819 }
2820
2821#if DEBUG_POINTER_ASSIGNMENT
2822 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
2823 for (size_t i = 0; i < heapSize; i++) {
2824 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2825 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2826 heap[i].distance);
2827 }
2828#endif
2829 }
2830
2831 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
2832 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
2833
2834 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
2835 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
2836
2837 matchedCurrentBits.markBit(currentPointerIndex);
2838 matchedLastBits.markBit(lastPointerIndex);
2839
2840 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
2841 mCurrentTouch.pointers[currentPointerIndex].id = id;
2842 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2843 usedIdBits.markBit(id);
2844
2845#if DEBUG_POINTER_ASSIGNMENT
2846 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
2847 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
2848#endif
2849 break;
2850 }
2851 }
2852
2853 // Assign fresh ids to new pointers.
2854 if (currentPointerCount > lastPointerCount) {
2855 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
2856 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
2857 uint32_t id = usedIdBits.firstUnmarkedBit();
2858
2859 mCurrentTouch.pointers[currentPointerIndex].id = id;
2860 mCurrentTouch.idToIndex[id] = currentPointerIndex;
2861 usedIdBits.markBit(id);
2862
2863#if DEBUG_POINTER_ASSIGNMENT
2864 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
2865 currentPointerIndex, id);
2866#endif
2867
2868 if (--i == 0) break; // done
2869 matchedCurrentBits.markBit(currentPointerIndex);
2870 }
2871 }
2872
2873 // Fix id bits.
2874 mCurrentTouch.idBits = usedIdBits;
2875 }
2876}
2877
2878/* Special hack for devices that have bad screen data: if one of the
2879 * points has moved more than a screen height from the last position,
2880 * then drop it. */
2881bool TouchInputMapper::applyBadTouchFilter() {
2882 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002883 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002884 return false;
2885 }
2886
2887 uint32_t pointerCount = mCurrentTouch.pointerCount;
2888
2889 // Nothing to do if there are no points.
2890 if (pointerCount == 0) {
2891 return false;
2892 }
2893
2894 // Don't do anything if a finger is going down or up. We run
2895 // here before assigning pointer IDs, so there isn't a good
2896 // way to do per-finger matching.
2897 if (pointerCount != mLastTouch.pointerCount) {
2898 return false;
2899 }
2900
2901 // We consider a single movement across more than a 7/16 of
2902 // the long size of the screen to be bad. This was a magic value
2903 // determined by looking at the maximum distance it is feasible
2904 // to actually move in one sample.
Jeff Brown8d608662010-08-30 03:02:23 -07002905 int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002906
2907 // XXX The original code in InputDevice.java included commented out
2908 // code for testing the X axis. Note that when we drop a point
2909 // we don't actually restore the old X either. Strange.
2910 // The old code also tries to track when bad points were previously
2911 // detected but it turns out that due to the placement of a "break"
2912 // at the end of the loop, we never set mDroppedBadPoint to true
2913 // so it is effectively dead code.
2914 // Need to figure out if the old code is busted or just overcomplicated
2915 // but working as intended.
2916
2917 // Look through all new points and see if any are farther than
2918 // acceptable from all previous points.
2919 for (uint32_t i = pointerCount; i-- > 0; ) {
2920 int32_t y = mCurrentTouch.pointers[i].y;
2921 int32_t closestY = INT_MAX;
2922 int32_t closestDeltaY = 0;
2923
2924#if DEBUG_HACKS
2925 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
2926#endif
2927
2928 for (uint32_t j = pointerCount; j-- > 0; ) {
2929 int32_t lastY = mLastTouch.pointers[j].y;
2930 int32_t deltaY = abs(y - lastY);
2931
2932#if DEBUG_HACKS
2933 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
2934 j, lastY, deltaY);
2935#endif
2936
2937 if (deltaY < maxDeltaY) {
2938 goto SkipSufficientlyClosePoint;
2939 }
2940 if (deltaY < closestDeltaY) {
2941 closestDeltaY = deltaY;
2942 closestY = lastY;
2943 }
2944 }
2945
2946 // Must not have found a close enough match.
2947#if DEBUG_HACKS
2948 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
2949 i, y, closestY, closestDeltaY, maxDeltaY);
2950#endif
2951
2952 mCurrentTouch.pointers[i].y = closestY;
2953 return true; // XXX original code only corrects one point
2954
2955 SkipSufficientlyClosePoint: ;
2956 }
2957
2958 // No change.
2959 return false;
2960}
2961
2962/* Special hack for devices that have bad screen data: drop points where
2963 * the coordinate value for one axis has jumped to the other pointer's location.
2964 */
2965bool TouchInputMapper::applyJumpyTouchFilter() {
2966 // This hack requires valid axis parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07002967 if (! mRawAxes.y.valid) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002968 return false;
2969 }
2970
2971 uint32_t pointerCount = mCurrentTouch.pointerCount;
2972 if (mLastTouch.pointerCount != pointerCount) {
2973#if DEBUG_HACKS
2974 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
2975 mLastTouch.pointerCount, pointerCount);
2976 for (uint32_t i = 0; i < pointerCount; i++) {
2977 LOGD(" Pointer %d (%d, %d)", i,
2978 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
2979 }
2980#endif
2981
2982 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
2983 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
2984 // Just drop the first few events going from 1 to 2 pointers.
2985 // They're bad often enough that they're not worth considering.
2986 mCurrentTouch.pointerCount = 1;
2987 mJumpyTouchFilter.jumpyPointsDropped += 1;
2988
2989#if DEBUG_HACKS
2990 LOGD("JumpyTouchFilter: Pointer 2 dropped");
2991#endif
2992 return true;
2993 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
2994 // The event when we go from 2 -> 1 tends to be messed up too
2995 mCurrentTouch.pointerCount = 2;
2996 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
2997 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
2998 mJumpyTouchFilter.jumpyPointsDropped += 1;
2999
3000#if DEBUG_HACKS
3001 for (int32_t i = 0; i < 2; i++) {
3002 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3003 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3004 }
3005#endif
3006 return true;
3007 }
3008 }
3009 // Reset jumpy points dropped on other transitions or if limit exceeded.
3010 mJumpyTouchFilter.jumpyPointsDropped = 0;
3011
3012#if DEBUG_HACKS
3013 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3014#endif
3015 return false;
3016 }
3017
3018 // We have the same number of pointers as last time.
3019 // A 'jumpy' point is one where the coordinate value for one axis
3020 // has jumped to the other pointer's location. No need to do anything
3021 // else if we only have one pointer.
3022 if (pointerCount < 2) {
3023 return false;
3024 }
3025
3026 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003027 int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003028
3029 // We only replace the single worst jumpy point as characterized by pointer distance
3030 // in a single axis.
3031 int32_t badPointerIndex = -1;
3032 int32_t badPointerReplacementIndex = -1;
3033 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3034
3035 for (uint32_t i = pointerCount; i-- > 0; ) {
3036 int32_t x = mCurrentTouch.pointers[i].x;
3037 int32_t y = mCurrentTouch.pointers[i].y;
3038
3039#if DEBUG_HACKS
3040 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3041#endif
3042
3043 // Check if a touch point is too close to another's coordinates
3044 bool dropX = false, dropY = false;
3045 for (uint32_t j = 0; j < pointerCount; j++) {
3046 if (i == j) {
3047 continue;
3048 }
3049
3050 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3051 dropX = true;
3052 break;
3053 }
3054
3055 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3056 dropY = true;
3057 break;
3058 }
3059 }
3060 if (! dropX && ! dropY) {
3061 continue; // not jumpy
3062 }
3063
3064 // Find a replacement candidate by comparing with older points on the
3065 // complementary (non-jumpy) axis.
3066 int32_t distance = INT_MIN; // distance to be corrected
3067 int32_t replacementIndex = -1;
3068
3069 if (dropX) {
3070 // X looks too close. Find an older replacement point with a close Y.
3071 int32_t smallestDeltaY = INT_MAX;
3072 for (uint32_t j = 0; j < pointerCount; j++) {
3073 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3074 if (deltaY < smallestDeltaY) {
3075 smallestDeltaY = deltaY;
3076 replacementIndex = j;
3077 }
3078 }
3079 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3080 } else {
3081 // Y looks too close. Find an older replacement point with a close X.
3082 int32_t smallestDeltaX = INT_MAX;
3083 for (uint32_t j = 0; j < pointerCount; j++) {
3084 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3085 if (deltaX < smallestDeltaX) {
3086 smallestDeltaX = deltaX;
3087 replacementIndex = j;
3088 }
3089 }
3090 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3091 }
3092
3093 // If replacing this pointer would correct a worse error than the previous ones
3094 // considered, then use this replacement instead.
3095 if (distance > badPointerDistance) {
3096 badPointerIndex = i;
3097 badPointerReplacementIndex = replacementIndex;
3098 badPointerDistance = distance;
3099 }
3100 }
3101
3102 // Correct the jumpy pointer if one was found.
3103 if (badPointerIndex >= 0) {
3104#if DEBUG_HACKS
3105 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3106 badPointerIndex,
3107 mLastTouch.pointers[badPointerReplacementIndex].x,
3108 mLastTouch.pointers[badPointerReplacementIndex].y);
3109#endif
3110
3111 mCurrentTouch.pointers[badPointerIndex].x =
3112 mLastTouch.pointers[badPointerReplacementIndex].x;
3113 mCurrentTouch.pointers[badPointerIndex].y =
3114 mLastTouch.pointers[badPointerReplacementIndex].y;
3115 mJumpyTouchFilter.jumpyPointsDropped += 1;
3116 return true;
3117 }
3118 }
3119
3120 mJumpyTouchFilter.jumpyPointsDropped = 0;
3121 return false;
3122}
3123
3124/* Special hack for devices that have bad screen data: aggregate and
3125 * compute averages of the coordinate data, to reduce the amount of
3126 * jitter seen by applications. */
3127void TouchInputMapper::applyAveragingTouchFilter() {
3128 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3129 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3130 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3131 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003132 int32_t pressure;
3133 switch (mCalibration.pressureSource) {
3134 case Calibration::PRESSURE_SOURCE_PRESSURE:
3135 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3136 break;
3137 case Calibration::PRESSURE_SOURCE_TOUCH:
3138 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3139 break;
3140 default:
3141 pressure = 1;
3142 break;
3143 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003144
3145 if (mLastTouch.idBits.hasBit(id)) {
3146 // Pointer was down before and is still down now.
3147 // Compute average over history trace.
3148 uint32_t start = mAveragingTouchFilter.historyStart[id];
3149 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3150
3151 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3152 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3153 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3154
3155#if DEBUG_HACKS
3156 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3157 id, distance);
3158#endif
3159
3160 if (distance < AVERAGING_DISTANCE_LIMIT) {
3161 // Increment end index in preparation for recording new historical data.
3162 end += 1;
3163 if (end > AVERAGING_HISTORY_SIZE) {
3164 end = 0;
3165 }
3166
3167 // If the end index has looped back to the start index then we have filled
3168 // the historical trace up to the desired size so we drop the historical
3169 // data at the start of the trace.
3170 if (end == start) {
3171 start += 1;
3172 if (start > AVERAGING_HISTORY_SIZE) {
3173 start = 0;
3174 }
3175 }
3176
3177 // Add the raw data to the historical trace.
3178 mAveragingTouchFilter.historyStart[id] = start;
3179 mAveragingTouchFilter.historyEnd[id] = end;
3180 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3181 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3182 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3183
3184 // Average over all historical positions in the trace by total pressure.
3185 int32_t averagedX = 0;
3186 int32_t averagedY = 0;
3187 int32_t totalPressure = 0;
3188 for (;;) {
3189 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3190 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3191 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3192 .pointers[id].pressure;
3193
3194 averagedX += historicalX * historicalPressure;
3195 averagedY += historicalY * historicalPressure;
3196 totalPressure += historicalPressure;
3197
3198 if (start == end) {
3199 break;
3200 }
3201
3202 start += 1;
3203 if (start > AVERAGING_HISTORY_SIZE) {
3204 start = 0;
3205 }
3206 }
3207
Jeff Brown8d608662010-08-30 03:02:23 -07003208 if (totalPressure != 0) {
3209 averagedX /= totalPressure;
3210 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003211
3212#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003213 LOGD("AveragingTouchFilter: Pointer id %d - "
3214 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3215 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003216#endif
3217
Jeff Brown8d608662010-08-30 03:02:23 -07003218 mCurrentTouch.pointers[currentIndex].x = averagedX;
3219 mCurrentTouch.pointers[currentIndex].y = averagedY;
3220 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003221 } else {
3222#if DEBUG_HACKS
3223 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3224#endif
3225 }
3226 } else {
3227#if DEBUG_HACKS
3228 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3229#endif
3230 }
3231
3232 // Reset pointer history.
3233 mAveragingTouchFilter.historyStart[id] = 0;
3234 mAveragingTouchFilter.historyEnd[id] = 0;
3235 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3236 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3237 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3238 }
3239}
3240
3241int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003242 { // acquire lock
3243 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003244
Jeff Brown6328cdc2010-07-29 18:18:33 -07003245 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003246 return AKEY_STATE_VIRTUAL;
3247 }
3248
Jeff Brown6328cdc2010-07-29 18:18:33 -07003249 size_t numVirtualKeys = mLocked.virtualKeys.size();
3250 for (size_t i = 0; i < numVirtualKeys; i++) {
3251 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003252 if (virtualKey.keyCode == keyCode) {
3253 return AKEY_STATE_UP;
3254 }
3255 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003256 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003257
3258 return AKEY_STATE_UNKNOWN;
3259}
3260
3261int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003262 { // acquire lock
3263 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003264
Jeff Brown6328cdc2010-07-29 18:18:33 -07003265 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003266 return AKEY_STATE_VIRTUAL;
3267 }
3268
Jeff Brown6328cdc2010-07-29 18:18:33 -07003269 size_t numVirtualKeys = mLocked.virtualKeys.size();
3270 for (size_t i = 0; i < numVirtualKeys; i++) {
3271 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003272 if (virtualKey.scanCode == scanCode) {
3273 return AKEY_STATE_UP;
3274 }
3275 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003276 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003277
3278 return AKEY_STATE_UNKNOWN;
3279}
3280
3281bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3282 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003283 { // acquire lock
3284 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003285
Jeff Brown6328cdc2010-07-29 18:18:33 -07003286 size_t numVirtualKeys = mLocked.virtualKeys.size();
3287 for (size_t i = 0; i < numVirtualKeys; i++) {
3288 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003289
3290 for (size_t i = 0; i < numCodes; i++) {
3291 if (virtualKey.keyCode == keyCodes[i]) {
3292 outFlags[i] = 1;
3293 }
3294 }
3295 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003296 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003297
3298 return true;
3299}
3300
3301
3302// --- SingleTouchInputMapper ---
3303
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003304SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3305 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003306 initialize();
3307}
3308
3309SingleTouchInputMapper::~SingleTouchInputMapper() {
3310}
3311
3312void SingleTouchInputMapper::initialize() {
3313 mAccumulator.clear();
3314
3315 mDown = false;
3316 mX = 0;
3317 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003318 mPressure = 0; // default to 0 for devices that don't report pressure
3319 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003320}
3321
3322void SingleTouchInputMapper::reset() {
3323 TouchInputMapper::reset();
3324
Jeff Brown6d0fec22010-07-23 21:28:06 -07003325 initialize();
3326 }
3327
3328void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3329 switch (rawEvent->type) {
3330 case EV_KEY:
3331 switch (rawEvent->scanCode) {
3332 case BTN_TOUCH:
3333 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3334 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003335 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3336 // not have received valid position information yet. This logic assumes that
3337 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003338 break;
3339 }
3340 break;
3341
3342 case EV_ABS:
3343 switch (rawEvent->scanCode) {
3344 case ABS_X:
3345 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3346 mAccumulator.absX = rawEvent->value;
3347 break;
3348 case ABS_Y:
3349 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3350 mAccumulator.absY = rawEvent->value;
3351 break;
3352 case ABS_PRESSURE:
3353 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3354 mAccumulator.absPressure = rawEvent->value;
3355 break;
3356 case ABS_TOOL_WIDTH:
3357 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3358 mAccumulator.absToolWidth = rawEvent->value;
3359 break;
3360 }
3361 break;
3362
3363 case EV_SYN:
3364 switch (rawEvent->scanCode) {
3365 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003366 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003367 break;
3368 }
3369 break;
3370 }
3371}
3372
3373void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003374 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003375 if (fields == 0) {
3376 return; // no new state changes, so nothing to do
3377 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003378
3379 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3380 mDown = mAccumulator.btnTouch;
3381 }
3382
3383 if (fields & Accumulator::FIELD_ABS_X) {
3384 mX = mAccumulator.absX;
3385 }
3386
3387 if (fields & Accumulator::FIELD_ABS_Y) {
3388 mY = mAccumulator.absY;
3389 }
3390
3391 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3392 mPressure = mAccumulator.absPressure;
3393 }
3394
3395 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003396 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003397 }
3398
3399 mCurrentTouch.clear();
3400
3401 if (mDown) {
3402 mCurrentTouch.pointerCount = 1;
3403 mCurrentTouch.pointers[0].id = 0;
3404 mCurrentTouch.pointers[0].x = mX;
3405 mCurrentTouch.pointers[0].y = mY;
3406 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003407 mCurrentTouch.pointers[0].touchMajor = 0;
3408 mCurrentTouch.pointers[0].touchMinor = 0;
3409 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3410 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003411 mCurrentTouch.pointers[0].orientation = 0;
3412 mCurrentTouch.idToIndex[0] = 0;
3413 mCurrentTouch.idBits.markBit(0);
3414 }
3415
3416 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003417
3418 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003419}
3420
Jeff Brown8d608662010-08-30 03:02:23 -07003421void SingleTouchInputMapper::configureRawAxes() {
3422 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003423
Jeff Brown8d608662010-08-30 03:02:23 -07003424 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3425 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3426 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3427 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003428}
3429
3430
3431// --- MultiTouchInputMapper ---
3432
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003433MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3434 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003435 initialize();
3436}
3437
3438MultiTouchInputMapper::~MultiTouchInputMapper() {
3439}
3440
3441void MultiTouchInputMapper::initialize() {
3442 mAccumulator.clear();
3443}
3444
3445void MultiTouchInputMapper::reset() {
3446 TouchInputMapper::reset();
3447
Jeff Brown6d0fec22010-07-23 21:28:06 -07003448 initialize();
3449}
3450
3451void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3452 switch (rawEvent->type) {
3453 case EV_ABS: {
3454 uint32_t pointerIndex = mAccumulator.pointerCount;
3455 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3456
3457 switch (rawEvent->scanCode) {
3458 case ABS_MT_POSITION_X:
3459 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3460 pointer->absMTPositionX = rawEvent->value;
3461 break;
3462 case ABS_MT_POSITION_Y:
3463 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3464 pointer->absMTPositionY = rawEvent->value;
3465 break;
3466 case ABS_MT_TOUCH_MAJOR:
3467 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3468 pointer->absMTTouchMajor = rawEvent->value;
3469 break;
3470 case ABS_MT_TOUCH_MINOR:
3471 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3472 pointer->absMTTouchMinor = rawEvent->value;
3473 break;
3474 case ABS_MT_WIDTH_MAJOR:
3475 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3476 pointer->absMTWidthMajor = rawEvent->value;
3477 break;
3478 case ABS_MT_WIDTH_MINOR:
3479 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3480 pointer->absMTWidthMinor = rawEvent->value;
3481 break;
3482 case ABS_MT_ORIENTATION:
3483 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3484 pointer->absMTOrientation = rawEvent->value;
3485 break;
3486 case ABS_MT_TRACKING_ID:
3487 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3488 pointer->absMTTrackingId = rawEvent->value;
3489 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003490 case ABS_MT_PRESSURE:
3491 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3492 pointer->absMTPressure = rawEvent->value;
3493 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003494 }
3495 break;
3496 }
3497
3498 case EV_SYN:
3499 switch (rawEvent->scanCode) {
3500 case SYN_MT_REPORT: {
3501 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3502 uint32_t pointerIndex = mAccumulator.pointerCount;
3503
3504 if (mAccumulator.pointers[pointerIndex].fields) {
3505 if (pointerIndex == MAX_POINTERS) {
3506 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3507 MAX_POINTERS);
3508 } else {
3509 pointerIndex += 1;
3510 mAccumulator.pointerCount = pointerIndex;
3511 }
3512 }
3513
3514 mAccumulator.pointers[pointerIndex].clear();
3515 break;
3516 }
3517
3518 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003519 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003520 break;
3521 }
3522 break;
3523 }
3524}
3525
3526void MultiTouchInputMapper::sync(nsecs_t when) {
3527 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003528 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003529
Jeff Brown6d0fec22010-07-23 21:28:06 -07003530 uint32_t inCount = mAccumulator.pointerCount;
3531 uint32_t outCount = 0;
3532 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003533
Jeff Brown6d0fec22010-07-23 21:28:06 -07003534 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003535
Jeff Brown6d0fec22010-07-23 21:28:06 -07003536 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003537 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3538 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003539
Jeff Brown6d0fec22010-07-23 21:28:06 -07003540 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003541 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3542 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07003543 continue;
3544 }
3545
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003546 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3547 outPointer.x = inPointer.absMTPositionX;
3548 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003549
Jeff Brown8d608662010-08-30 03:02:23 -07003550 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3551 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003552 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3553 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003554 continue;
3555 }
Jeff Brown8d608662010-08-30 03:02:23 -07003556 outPointer.pressure = inPointer.absMTPressure;
3557 } else {
3558 // Default pressure to 0 if absent.
3559 outPointer.pressure = 0;
3560 }
3561
3562 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3563 if (inPointer.absMTTouchMajor <= 0) {
3564 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3565 // a pointer going up. Drop this finger.
3566 continue;
3567 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003568 outPointer.touchMajor = inPointer.absMTTouchMajor;
3569 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003570 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003571 outPointer.touchMajor = 0;
3572 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003573
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003574 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3575 outPointer.touchMinor = inPointer.absMTTouchMinor;
3576 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003577 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003578 outPointer.touchMinor = outPointer.touchMajor;
3579 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003580
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003581 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3582 outPointer.toolMajor = inPointer.absMTWidthMajor;
3583 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003584 // Default tool area to 0 if absent.
3585 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003586 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003587
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003588 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3589 outPointer.toolMinor = inPointer.absMTWidthMinor;
3590 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003591 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003592 outPointer.toolMinor = outPointer.toolMajor;
3593 }
3594
3595 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3596 outPointer.orientation = inPointer.absMTOrientation;
3597 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003598 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003599 outPointer.orientation = 0;
3600 }
3601
Jeff Brown8d608662010-08-30 03:02:23 -07003602 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003603 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003604 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3605 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003606
Jeff Brown6d0fec22010-07-23 21:28:06 -07003607 if (id > MAX_POINTER_ID) {
3608#if DEBUG_POINTERS
3609 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003610 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003611 id, MAX_POINTER_ID);
3612#endif
3613 havePointerIds = false;
3614 }
3615 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003616 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003617 mCurrentTouch.idToIndex[id] = outCount;
3618 mCurrentTouch.idBits.markBit(id);
3619 }
3620 } else {
3621 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003622 }
3623 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003624
Jeff Brown6d0fec22010-07-23 21:28:06 -07003625 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003626 }
3627
Jeff Brown6d0fec22010-07-23 21:28:06 -07003628 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003629
Jeff Brown6d0fec22010-07-23 21:28:06 -07003630 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003631
3632 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003633}
3634
Jeff Brown8d608662010-08-30 03:02:23 -07003635void MultiTouchInputMapper::configureRawAxes() {
3636 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003637
Jeff Brown8d608662010-08-30 03:02:23 -07003638 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3639 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3640 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3641 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3642 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3643 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3644 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3645 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003646}
3647
Jeff Brown46b9ac02010-04-22 18:58:52 -07003648
3649} // namespace android