blob: 67074a38b2680f7843b0e708b84153e1666a7b81 [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownb4ff35d2011-01-02 16:37:43 -080036#include "InputReader.h"
37
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080039#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080040#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070041
42#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070043#include <stdlib.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070045#include <errno.h>
46#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070047#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048
Jeff Brown8d608662010-08-30 03:02:23 -070049#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070050#define INDENT2 " "
51#define INDENT3 " "
52#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070053
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070054namespace android {
55
56// --- Static Functions ---
57
58template<typename T>
59inline static T abs(const T& value) {
60 return value < 0 ? - value : value;
61}
62
63template<typename T>
64inline static T min(const T& a, const T& b) {
65 return a < b ? a : b;
66}
67
Jeff Brown5c225b12010-06-16 01:53:36 -070068template<typename T>
69inline static void swap(T& a, T& b) {
70 T temp = a;
71 a = b;
72 b = temp;
73}
74
Jeff Brown8d608662010-08-30 03:02:23 -070075inline static float avg(float x, float y) {
76 return (x + y) / 2;
77}
78
79inline static float pythag(float x, float y) {
80 return sqrtf(x * x + y * y);
81}
82
Jeff Brown517bb4c2011-01-14 19:09:23 -080083inline static int32_t signExtendNybble(int32_t value) {
84 return value >= 8 ? value - 16 : value;
85}
86
Jeff Brownef3d7e82010-09-30 14:33:04 -070087static inline const char* toString(bool value) {
88 return value ? "true" : "false";
89}
90
Jeff Brownd41cff22011-03-03 02:09:54 -080091static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
92 const int32_t map[][4], size_t mapSize) {
93 if (orientation != DISPLAY_ORIENTATION_0) {
94 for (size_t i = 0; i < mapSize; i++) {
95 if (value == map[i][0]) {
96 return map[i][orientation];
97 }
98 }
99 }
100 return value;
101}
102
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700103static const int32_t keyCodeRotationMap[][4] = {
104 // key codes enumerated counter-clockwise with the original (unrotated) key first
105 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -0700106 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
107 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
108 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
109 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700110};
Jeff Brownd41cff22011-03-03 02:09:54 -0800111static const size_t keyCodeRotationMapSize =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700112 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
113
114int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -0800115 return rotateValueUsingRotationMap(keyCode, orientation,
116 keyCodeRotationMap, keyCodeRotationMapSize);
117}
118
119static const int32_t edgeFlagRotationMap[][4] = {
120 // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
121 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
122 { AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT,
123 AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT },
124 { AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP,
125 AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM },
126 { AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT,
127 AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT },
128 { AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM,
129 AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP },
130};
131static const size_t edgeFlagRotationMapSize =
132 sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
133
134static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
135 return rotateValueUsingRotationMap(edgeFlag, orientation,
136 edgeFlagRotationMap, edgeFlagRotationMapSize);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700137}
138
Jeff Brown6d0fec22010-07-23 21:28:06 -0700139static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
140 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
141}
142
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700143
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700144// --- InputReader ---
145
146InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700147 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700148 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700149 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brownfe508922011-01-18 15:10:10 -0800150 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700151 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700152 updateGlobalMetaState();
153 updateInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700154}
155
156InputReader::~InputReader() {
157 for (size_t i = 0; i < mDevices.size(); i++) {
158 delete mDevices.valueAt(i);
159 }
160}
161
162void InputReader::loopOnce() {
163 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700164 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700165
166#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800167 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700168 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
169 rawEvent.value);
170#endif
171
172 process(& rawEvent);
173}
174
175void InputReader::process(const RawEvent* rawEvent) {
176 switch (rawEvent->type) {
177 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700178 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700179 break;
180
181 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700182 removeDevice(rawEvent->deviceId);
183 break;
184
185 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700186 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700187 break;
188
Jeff Brown6d0fec22010-07-23 21:28:06 -0700189 default:
190 consumeEvent(rawEvent);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700191 break;
192 }
193}
194
Jeff Brown7342bb92010-10-01 18:55:43 -0700195void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700196 String8 name = mEventHub->getDeviceName(deviceId);
197 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
198
199 InputDevice* device = createDevice(deviceId, name, classes);
200 device->configure();
201
Jeff Brown8d608662010-08-30 03:02:23 -0700202 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800203 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700204 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800205 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700206 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700207 }
208
Jeff Brown6d0fec22010-07-23 21:28:06 -0700209 bool added = false;
210 { // acquire device registry writer lock
211 RWLock::AutoWLock _wl(mDeviceRegistryLock);
212
213 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
214 if (deviceIndex < 0) {
215 mDevices.add(deviceId, device);
216 added = true;
217 }
218 } // release device registry writer lock
219
220 if (! added) {
221 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
222 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700223 return;
224 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700225}
226
Jeff Brown7342bb92010-10-01 18:55:43 -0700227void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700228 bool removed = false;
229 InputDevice* device = NULL;
230 { // acquire device registry writer lock
231 RWLock::AutoWLock _wl(mDeviceRegistryLock);
232
233 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
234 if (deviceIndex >= 0) {
235 device = mDevices.valueAt(deviceIndex);
236 mDevices.removeItemsAt(deviceIndex, 1);
237 removed = true;
238 }
239 } // release device registry writer lock
240
241 if (! removed) {
242 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700243 return;
244 }
245
Jeff Brown6d0fec22010-07-23 21:28:06 -0700246 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800247 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700248 device->getId(), device->getName().string());
249 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800250 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700251 device->getId(), device->getName().string(), device->getSources());
252 }
253
Jeff Brown8d608662010-08-30 03:02:23 -0700254 device->reset();
255
Jeff Brown6d0fec22010-07-23 21:28:06 -0700256 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700257}
258
Jeff Brown6d0fec22010-07-23 21:28:06 -0700259InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
260 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700261
Jeff Brown56194eb2011-03-02 19:23:13 -0800262 // External devices.
263 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
264 device->setExternal(true);
265 }
266
Jeff Brown6d0fec22010-07-23 21:28:06 -0700267 // Switch-like devices.
268 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
269 device->addMapper(new SwitchInputMapper(device));
270 }
271
272 // Keyboard-like devices.
273 uint32_t keyboardSources = 0;
274 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
275 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
276 keyboardSources |= AINPUT_SOURCE_KEYBOARD;
277 }
278 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
279 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
280 }
281 if (classes & INPUT_DEVICE_CLASS_DPAD) {
282 keyboardSources |= AINPUT_SOURCE_DPAD;
283 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800284 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
285 keyboardSources |= AINPUT_SOURCE_GAMEPAD;
286 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700287
288 if (keyboardSources != 0) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800289 device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700290 }
291
Jeff Brown83c09682010-12-23 17:50:18 -0800292 // Cursor-like devices.
293 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
294 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700295 }
296
Jeff Brown58a2da82011-01-25 16:02:22 -0800297 // Touchscreens and touchpad devices.
298 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800299 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800300 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800301 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700302 }
303
Jeff Browncb1404e2011-01-15 18:14:15 -0800304 // Joystick-like devices.
305 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
306 device->addMapper(new JoystickInputMapper(device));
307 }
308
Jeff Brown6d0fec22010-07-23 21:28:06 -0700309 return device;
310}
311
312void InputReader::consumeEvent(const RawEvent* rawEvent) {
313 int32_t deviceId = rawEvent->deviceId;
314
315 { // acquire device registry reader lock
316 RWLock::AutoRLock _rl(mDeviceRegistryLock);
317
318 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
319 if (deviceIndex < 0) {
320 LOGW("Discarding event for unknown deviceId %d.", deviceId);
321 return;
322 }
323
324 InputDevice* device = mDevices.valueAt(deviceIndex);
325 if (device->isIgnored()) {
326 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
327 return;
328 }
329
330 device->process(rawEvent);
331 } // release device registry reader lock
332}
333
Jeff Brownc3db8582010-10-20 15:33:38 -0700334void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700335 // Reset global meta state because it depends on the list of all configured devices.
336 updateGlobalMetaState();
337
338 // Update input configuration.
339 updateInputConfiguration();
340
341 // Enqueue configuration changed.
342 mDispatcher->notifyConfigurationChanged(when);
343}
344
345void InputReader::configureExcludedDevices() {
346 Vector<String8> excludedDeviceNames;
347 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
348
349 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
350 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
351 }
352}
353
354void InputReader::updateGlobalMetaState() {
355 { // acquire state lock
356 AutoMutex _l(mStateLock);
357
358 mGlobalMetaState = 0;
359
360 { // acquire device registry reader lock
361 RWLock::AutoRLock _rl(mDeviceRegistryLock);
362
363 for (size_t i = 0; i < mDevices.size(); i++) {
364 InputDevice* device = mDevices.valueAt(i);
365 mGlobalMetaState |= device->getMetaState();
366 }
367 } // release device registry reader lock
368 } // release state lock
369}
370
371int32_t InputReader::getGlobalMetaState() {
372 { // acquire state lock
373 AutoMutex _l(mStateLock);
374
375 return mGlobalMetaState;
376 } // release state lock
377}
378
379void InputReader::updateInputConfiguration() {
380 { // acquire state lock
381 AutoMutex _l(mStateLock);
382
383 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
384 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
385 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
386 { // acquire device registry reader lock
387 RWLock::AutoRLock _rl(mDeviceRegistryLock);
388
389 InputDeviceInfo deviceInfo;
390 for (size_t i = 0; i < mDevices.size(); i++) {
391 InputDevice* device = mDevices.valueAt(i);
392 device->getDeviceInfo(& deviceInfo);
393 uint32_t sources = deviceInfo.getSources();
394
395 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
396 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
397 }
398 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
399 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
400 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
401 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
402 }
403 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
404 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700405 }
406 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700407 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700408
Jeff Brown6d0fec22010-07-23 21:28:06 -0700409 mInputConfiguration.touchScreen = touchScreenConfig;
410 mInputConfiguration.keyboard = keyboardConfig;
411 mInputConfiguration.navigation = navigationConfig;
412 } // release state lock
413}
414
Jeff Brownfe508922011-01-18 15:10:10 -0800415void InputReader::disableVirtualKeysUntil(nsecs_t time) {
416 mDisableVirtualKeysTimeout = time;
417}
418
419bool InputReader::shouldDropVirtualKey(nsecs_t now,
420 InputDevice* device, int32_t keyCode, int32_t scanCode) {
421 if (now < mDisableVirtualKeysTimeout) {
422 LOGI("Dropping virtual key from device %s because virtual keys are "
423 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
424 device->getName().string(),
425 (mDisableVirtualKeysTimeout - now) * 0.000001,
426 keyCode, scanCode);
427 return true;
428 } else {
429 return false;
430 }
431}
432
Jeff Brown05dc66a2011-03-02 14:41:58 -0800433void InputReader::fadePointer() {
434 { // acquire device registry reader lock
435 RWLock::AutoRLock _rl(mDeviceRegistryLock);
436
437 for (size_t i = 0; i < mDevices.size(); i++) {
438 InputDevice* device = mDevices.valueAt(i);
439 device->fadePointer();
440 }
441 } // release device registry reader lock
442}
443
Jeff Brown6d0fec22010-07-23 21:28:06 -0700444void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
445 { // acquire state lock
446 AutoMutex _l(mStateLock);
447
448 *outConfiguration = mInputConfiguration;
449 } // release state lock
450}
451
452status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
453 { // acquire device registry reader lock
454 RWLock::AutoRLock _rl(mDeviceRegistryLock);
455
456 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
457 if (deviceIndex < 0) {
458 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700459 }
460
Jeff Brown6d0fec22010-07-23 21:28:06 -0700461 InputDevice* device = mDevices.valueAt(deviceIndex);
462 if (device->isIgnored()) {
463 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700464 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700465
466 device->getDeviceInfo(outDeviceInfo);
467 return OK;
468 } // release device registy reader lock
469}
470
471void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
472 outDeviceIds.clear();
473
474 { // acquire device registry reader lock
475 RWLock::AutoRLock _rl(mDeviceRegistryLock);
476
477 size_t numDevices = mDevices.size();
478 for (size_t i = 0; i < numDevices; i++) {
479 InputDevice* device = mDevices.valueAt(i);
480 if (! device->isIgnored()) {
481 outDeviceIds.add(device->getId());
482 }
483 }
484 } // release device registy reader lock
485}
486
487int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
488 int32_t keyCode) {
489 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
490}
491
492int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
493 int32_t scanCode) {
494 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
495}
496
497int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
498 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
499}
500
501int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
502 GetStateFunc getStateFunc) {
503 { // acquire device registry reader lock
504 RWLock::AutoRLock _rl(mDeviceRegistryLock);
505
506 int32_t result = AKEY_STATE_UNKNOWN;
507 if (deviceId >= 0) {
508 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
509 if (deviceIndex >= 0) {
510 InputDevice* device = mDevices.valueAt(deviceIndex);
511 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
512 result = (device->*getStateFunc)(sourceMask, code);
513 }
514 }
515 } else {
516 size_t numDevices = mDevices.size();
517 for (size_t i = 0; i < numDevices; i++) {
518 InputDevice* device = mDevices.valueAt(i);
519 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
520 result = (device->*getStateFunc)(sourceMask, code);
521 if (result >= AKEY_STATE_DOWN) {
522 return result;
523 }
524 }
525 }
526 }
527 return result;
528 } // release device registy reader lock
529}
530
531bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
532 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
533 memset(outFlags, 0, numCodes);
534 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
535}
536
537bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
538 const int32_t* keyCodes, uint8_t* outFlags) {
539 { // acquire device registry reader lock
540 RWLock::AutoRLock _rl(mDeviceRegistryLock);
541 bool result = false;
542 if (deviceId >= 0) {
543 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
544 if (deviceIndex >= 0) {
545 InputDevice* device = mDevices.valueAt(deviceIndex);
546 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
547 result = device->markSupportedKeyCodes(sourceMask,
548 numCodes, keyCodes, outFlags);
549 }
550 }
551 } else {
552 size_t numDevices = mDevices.size();
553 for (size_t i = 0; i < numDevices; i++) {
554 InputDevice* device = mDevices.valueAt(i);
555 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
556 result |= device->markSupportedKeyCodes(sourceMask,
557 numCodes, keyCodes, outFlags);
558 }
559 }
560 }
561 return result;
562 } // release device registy reader lock
563}
564
Jeff Brownb88102f2010-09-08 11:49:43 -0700565void InputReader::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -0700566 mEventHub->dump(dump);
567 dump.append("\n");
568
569 dump.append("Input Reader State:\n");
570
Jeff Brownef3d7e82010-09-30 14:33:04 -0700571 { // acquire device registry reader lock
572 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700573
Jeff Brownef3d7e82010-09-30 14:33:04 -0700574 for (size_t i = 0; i < mDevices.size(); i++) {
575 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700576 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700577 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700578}
579
Jeff Brown6d0fec22010-07-23 21:28:06 -0700580
581// --- InputReaderThread ---
582
583InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
584 Thread(/*canCallJava*/ true), mReader(reader) {
585}
586
587InputReaderThread::~InputReaderThread() {
588}
589
590bool InputReaderThread::threadLoop() {
591 mReader->loopOnce();
592 return true;
593}
594
595
596// --- InputDevice ---
597
598InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
Jeff Brown56194eb2011-03-02 19:23:13 -0800599 mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700600}
601
602InputDevice::~InputDevice() {
603 size_t numMappers = mMappers.size();
604 for (size_t i = 0; i < numMappers; i++) {
605 delete mMappers[i];
606 }
607 mMappers.clear();
608}
609
Jeff Brownef3d7e82010-09-30 14:33:04 -0700610void InputDevice::dump(String8& dump) {
611 InputDeviceInfo deviceInfo;
612 getDeviceInfo(& deviceInfo);
613
Jeff Brown90655042010-12-02 13:50:46 -0800614 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700615 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800616 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700617 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
618 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800619
620 const KeyedVector<int32_t, InputDeviceInfo::MotionRange> ranges = deviceInfo.getMotionRanges();
621 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700622 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800623 for (size_t i = 0; i < ranges.size(); i++) {
624 int32_t axis = ranges.keyAt(i);
625 const char* label = getAxisLabel(axis);
626 char name[32];
627 if (label) {
628 strncpy(name, label, sizeof(name));
629 name[sizeof(name) - 1] = '\0';
630 } else {
631 snprintf(name, sizeof(name), "%d", axis);
632 }
633 const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
634 dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
635 name, range.min, range.max, range.flat, range.fuzz);
636 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700637 }
638
639 size_t numMappers = mMappers.size();
640 for (size_t i = 0; i < numMappers; i++) {
641 InputMapper* mapper = mMappers[i];
642 mapper->dump(dump);
643 }
644}
645
Jeff Brown6d0fec22010-07-23 21:28:06 -0700646void InputDevice::addMapper(InputMapper* mapper) {
647 mMappers.add(mapper);
648}
649
650void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700651 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800652 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700653 }
654
Jeff Brown6d0fec22010-07-23 21:28:06 -0700655 mSources = 0;
656
657 size_t numMappers = mMappers.size();
658 for (size_t i = 0; i < numMappers; i++) {
659 InputMapper* mapper = mMappers[i];
660 mapper->configure();
661 mSources |= mapper->getSources();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700662 }
663}
664
Jeff Brown6d0fec22010-07-23 21:28:06 -0700665void InputDevice::reset() {
666 size_t numMappers = mMappers.size();
667 for (size_t i = 0; i < numMappers; i++) {
668 InputMapper* mapper = mMappers[i];
669 mapper->reset();
670 }
671}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700672
Jeff Brown6d0fec22010-07-23 21:28:06 -0700673void InputDevice::process(const RawEvent* rawEvent) {
674 size_t numMappers = mMappers.size();
675 for (size_t i = 0; i < numMappers; i++) {
676 InputMapper* mapper = mMappers[i];
677 mapper->process(rawEvent);
678 }
679}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700680
Jeff Brown6d0fec22010-07-23 21:28:06 -0700681void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
682 outDeviceInfo->initialize(mId, mName);
683
684 size_t numMappers = mMappers.size();
685 for (size_t i = 0; i < numMappers; i++) {
686 InputMapper* mapper = mMappers[i];
687 mapper->populateDeviceInfo(outDeviceInfo);
688 }
689}
690
691int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
692 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
693}
694
695int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
696 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
697}
698
699int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
700 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
701}
702
703int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
704 int32_t result = AKEY_STATE_UNKNOWN;
705 size_t numMappers = mMappers.size();
706 for (size_t i = 0; i < numMappers; i++) {
707 InputMapper* mapper = mMappers[i];
708 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
709 result = (mapper->*getStateFunc)(sourceMask, code);
710 if (result >= AKEY_STATE_DOWN) {
711 return result;
712 }
713 }
714 }
715 return result;
716}
717
718bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
719 const int32_t* keyCodes, uint8_t* outFlags) {
720 bool result = false;
721 size_t numMappers = mMappers.size();
722 for (size_t i = 0; i < numMappers; i++) {
723 InputMapper* mapper = mMappers[i];
724 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
725 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
726 }
727 }
728 return result;
729}
730
731int32_t InputDevice::getMetaState() {
732 int32_t result = 0;
733 size_t numMappers = mMappers.size();
734 for (size_t i = 0; i < numMappers; i++) {
735 InputMapper* mapper = mMappers[i];
736 result |= mapper->getMetaState();
737 }
738 return result;
739}
740
Jeff Brown05dc66a2011-03-02 14:41:58 -0800741void InputDevice::fadePointer() {
742 size_t numMappers = mMappers.size();
743 for (size_t i = 0; i < numMappers; i++) {
744 InputMapper* mapper = mMappers[i];
745 mapper->fadePointer();
746 }
747}
748
Jeff Brown6d0fec22010-07-23 21:28:06 -0700749
750// --- InputMapper ---
751
752InputMapper::InputMapper(InputDevice* device) :
753 mDevice(device), mContext(device->getContext()) {
754}
755
756InputMapper::~InputMapper() {
757}
758
759void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
760 info->addSource(getSources());
761}
762
Jeff Brownef3d7e82010-09-30 14:33:04 -0700763void InputMapper::dump(String8& dump) {
764}
765
Jeff Brown6d0fec22010-07-23 21:28:06 -0700766void InputMapper::configure() {
767}
768
769void InputMapper::reset() {
770}
771
772int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
773 return AKEY_STATE_UNKNOWN;
774}
775
776int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
777 return AKEY_STATE_UNKNOWN;
778}
779
780int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
781 return AKEY_STATE_UNKNOWN;
782}
783
784bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
785 const int32_t* keyCodes, uint8_t* outFlags) {
786 return false;
787}
788
789int32_t InputMapper::getMetaState() {
790 return 0;
791}
792
Jeff Brown05dc66a2011-03-02 14:41:58 -0800793void InputMapper::fadePointer() {
794}
795
Jeff Browncb1404e2011-01-15 18:14:15 -0800796void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
797 const RawAbsoluteAxisInfo& axis, const char* name) {
798 if (axis.valid) {
799 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
800 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
801 } else {
802 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
803 }
804}
805
Jeff Brown6d0fec22010-07-23 21:28:06 -0700806
807// --- SwitchInputMapper ---
808
809SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
810 InputMapper(device) {
811}
812
813SwitchInputMapper::~SwitchInputMapper() {
814}
815
816uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800817 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700818}
819
820void SwitchInputMapper::process(const RawEvent* rawEvent) {
821 switch (rawEvent->type) {
822 case EV_SW:
823 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
824 break;
825 }
826}
827
828void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700829 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700830}
831
832int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
833 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
834}
835
836
837// --- KeyboardInputMapper ---
838
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800839KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700840 uint32_t sources, int32_t keyboardType) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800841 InputMapper(device), mSources(sources),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700842 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700843 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700844}
845
846KeyboardInputMapper::~KeyboardInputMapper() {
847}
848
Jeff Brown6328cdc2010-07-29 18:18:33 -0700849void KeyboardInputMapper::initializeLocked() {
850 mLocked.metaState = AMETA_NONE;
851 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700852}
853
854uint32_t KeyboardInputMapper::getSources() {
855 return mSources;
856}
857
858void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
859 InputMapper::populateDeviceInfo(info);
860
861 info->setKeyboardType(mKeyboardType);
862}
863
Jeff Brownef3d7e82010-09-30 14:33:04 -0700864void KeyboardInputMapper::dump(String8& dump) {
865 { // acquire lock
866 AutoMutex _l(mLock);
867 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800868 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700869 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
870 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
871 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
872 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
873 } // release lock
874}
875
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800876
877void KeyboardInputMapper::configure() {
878 InputMapper::configure();
879
880 // Configure basic parameters.
881 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800882
883 // Reset LEDs.
884 {
885 AutoMutex _l(mLock);
886 resetLedStateLocked();
887 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800888}
889
890void KeyboardInputMapper::configureParameters() {
891 mParameters.orientationAware = false;
892 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
893 mParameters.orientationAware);
894
895 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
896}
897
898void KeyboardInputMapper::dumpParameters(String8& dump) {
899 dump.append(INDENT3 "Parameters:\n");
900 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
901 mParameters.associatedDisplayId);
902 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
903 toString(mParameters.orientationAware));
904}
905
Jeff Brown6d0fec22010-07-23 21:28:06 -0700906void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700907 for (;;) {
908 int32_t keyCode, scanCode;
909 { // acquire lock
910 AutoMutex _l(mLock);
911
912 // Synthesize key up event on reset if keys are currently down.
913 if (mLocked.keyDowns.isEmpty()) {
914 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800915 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700916 break; // done
917 }
918
919 const KeyDown& keyDown = mLocked.keyDowns.top();
920 keyCode = keyDown.keyCode;
921 scanCode = keyDown.scanCode;
922 } // release lock
923
Jeff Brown6d0fec22010-07-23 21:28:06 -0700924 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700925 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700926 }
927
928 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700929 getContext()->updateGlobalMetaState();
930}
931
932void KeyboardInputMapper::process(const RawEvent* rawEvent) {
933 switch (rawEvent->type) {
934 case EV_KEY: {
935 int32_t scanCode = rawEvent->scanCode;
936 if (isKeyboardOrGamepadKey(scanCode)) {
937 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
938 rawEvent->flags);
939 }
940 break;
941 }
942 }
943}
944
945bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
946 return scanCode < BTN_MOUSE
947 || scanCode >= KEY_OK
Jeff Browncb1404e2011-01-15 18:14:15 -0800948 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700949}
950
Jeff Brown6328cdc2010-07-29 18:18:33 -0700951void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
952 int32_t scanCode, uint32_t policyFlags) {
953 int32_t newMetaState;
954 nsecs_t downTime;
955 bool metaStateChanged = false;
956
957 { // acquire lock
958 AutoMutex _l(mLock);
959
960 if (down) {
961 // Rotate key codes according to orientation if needed.
962 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800963 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700964 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800965 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
966 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -0800967 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700968 }
969
970 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700971 }
972
Jeff Brown6328cdc2010-07-29 18:18:33 -0700973 // Add key down.
974 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
975 if (keyDownIndex >= 0) {
976 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800977 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700978 } else {
979 // key down
Jeff Brownfe508922011-01-18 15:10:10 -0800980 if ((policyFlags & POLICY_FLAG_VIRTUAL)
981 && mContext->shouldDropVirtualKey(when,
982 getDevice(), keyCode, scanCode)) {
983 return;
984 }
985
Jeff Brown6328cdc2010-07-29 18:18:33 -0700986 mLocked.keyDowns.push();
987 KeyDown& keyDown = mLocked.keyDowns.editTop();
988 keyDown.keyCode = keyCode;
989 keyDown.scanCode = scanCode;
990 }
991
992 mLocked.downTime = when;
993 } else {
994 // Remove key down.
995 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
996 if (keyDownIndex >= 0) {
997 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800998 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -0700999 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1000 } else {
1001 // key was not actually down
1002 LOGI("Dropping key up from device %s because the key was not down. "
1003 "keyCode=%d, scanCode=%d",
1004 getDeviceName().string(), keyCode, scanCode);
1005 return;
1006 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001007 }
1008
Jeff Brown6328cdc2010-07-29 18:18:33 -07001009 int32_t oldMetaState = mLocked.metaState;
1010 newMetaState = updateMetaState(keyCode, down, oldMetaState);
1011 if (oldMetaState != newMetaState) {
1012 mLocked.metaState = newMetaState;
1013 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -07001014 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001015 }
Jeff Brownfd035822010-06-30 16:10:35 -07001016
Jeff Brown6328cdc2010-07-29 18:18:33 -07001017 downTime = mLocked.downTime;
1018 } // release lock
1019
Jeff Brown56194eb2011-03-02 19:23:13 -08001020 // Key down on external an keyboard should wake the device.
1021 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1022 // For internal keyboards, the key layout file should specify the policy flags for
1023 // each wake key individually.
1024 // TODO: Use the input device configuration to control this behavior more finely.
1025 if (down && getDevice()->isExternal()
1026 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1027 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1028 }
1029
Jeff Brown6328cdc2010-07-29 18:18:33 -07001030 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001031 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001032 }
1033
Jeff Brown05dc66a2011-03-02 14:41:58 -08001034 if (down && !isMetaKey(keyCode)) {
1035 getContext()->fadePointer();
1036 }
1037
Jeff Brown497a92c2010-09-12 17:55:08 -07001038 if (policyFlags & POLICY_FLAG_FUNCTION) {
1039 newMetaState |= AMETA_FUNCTION_ON;
1040 }
Jeff Brown83c09682010-12-23 17:50:18 -08001041 getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001042 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1043 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001044}
1045
Jeff Brown6328cdc2010-07-29 18:18:33 -07001046ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1047 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001048 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001049 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001050 return i;
1051 }
1052 }
1053 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001054}
1055
Jeff Brown6d0fec22010-07-23 21:28:06 -07001056int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1057 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1058}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001059
Jeff Brown6d0fec22010-07-23 21:28:06 -07001060int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1061 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1062}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001063
Jeff Brown6d0fec22010-07-23 21:28:06 -07001064bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1065 const int32_t* keyCodes, uint8_t* outFlags) {
1066 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1067}
1068
1069int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001070 { // acquire lock
1071 AutoMutex _l(mLock);
1072 return mLocked.metaState;
1073 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001074}
1075
Jeff Brown49ed71d2010-12-06 17:13:33 -08001076void KeyboardInputMapper::resetLedStateLocked() {
1077 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1078 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1079 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1080
1081 updateLedStateLocked(true);
1082}
1083
1084void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1085 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1086 ledState.on = false;
1087}
1088
Jeff Brown497a92c2010-09-12 17:55:08 -07001089void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1090 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001091 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001092 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001093 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001094 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001095 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001096}
1097
1098void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1099 int32_t led, int32_t modifier, bool reset) {
1100 if (ledState.avail) {
1101 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001102 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001103 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1104 ledState.on = desiredState;
1105 }
1106 }
1107}
1108
Jeff Brown6d0fec22010-07-23 21:28:06 -07001109
Jeff Brown83c09682010-12-23 17:50:18 -08001110// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001111
Jeff Brown83c09682010-12-23 17:50:18 -08001112CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001113 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001114 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001115}
1116
Jeff Brown83c09682010-12-23 17:50:18 -08001117CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001118}
1119
Jeff Brown83c09682010-12-23 17:50:18 -08001120uint32_t CursorInputMapper::getSources() {
1121 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001122}
1123
Jeff Brown83c09682010-12-23 17:50:18 -08001124void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001125 InputMapper::populateDeviceInfo(info);
1126
Jeff Brown83c09682010-12-23 17:50:18 -08001127 if (mParameters.mode == Parameters::MODE_POINTER) {
1128 float minX, minY, maxX, maxY;
1129 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001130 info->addMotionRange(AMOTION_EVENT_AXIS_X, minX, maxX, 0.0f, 0.0f);
1131 info->addMotionRange(AMOTION_EVENT_AXIS_Y, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001132 }
1133 } else {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001134 info->addMotionRange(AMOTION_EVENT_AXIS_X, -1.0f, 1.0f, 0.0f, mXScale);
1135 info->addMotionRange(AMOTION_EVENT_AXIS_Y, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001136 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001137 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
1138
1139 if (mHaveVWheel) {
1140 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1141 }
1142 if (mHaveHWheel) {
1143 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, -1.0f, 1.0f, 0.0f, 0.0f);
1144 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001145}
1146
Jeff Brown83c09682010-12-23 17:50:18 -08001147void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001148 { // acquire lock
1149 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001150 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001151 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001152 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1153 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001154 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1155 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001156 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1157 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1158 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1159 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001160 dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
1161 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1162 } // release lock
1163}
1164
Jeff Brown83c09682010-12-23 17:50:18 -08001165void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001166 InputMapper::configure();
1167
1168 // Configure basic parameters.
1169 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001170
1171 // Configure device mode.
1172 switch (mParameters.mode) {
1173 case Parameters::MODE_POINTER:
1174 mSources = AINPUT_SOURCE_MOUSE;
1175 mXPrecision = 1.0f;
1176 mYPrecision = 1.0f;
1177 mXScale = 1.0f;
1178 mYScale = 1.0f;
1179 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1180 break;
1181 case Parameters::MODE_NAVIGATION:
1182 mSources = AINPUT_SOURCE_TRACKBALL;
1183 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1184 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1185 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1186 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1187 break;
1188 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001189
1190 mVWheelScale = 1.0f;
1191 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001192
1193 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1194 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001195}
1196
Jeff Brown83c09682010-12-23 17:50:18 -08001197void CursorInputMapper::configureParameters() {
1198 mParameters.mode = Parameters::MODE_POINTER;
1199 String8 cursorModeString;
1200 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1201 if (cursorModeString == "navigation") {
1202 mParameters.mode = Parameters::MODE_NAVIGATION;
1203 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1204 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1205 }
1206 }
1207
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001208 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001209 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001210 mParameters.orientationAware);
1211
Jeff Brown83c09682010-12-23 17:50:18 -08001212 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1213 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001214}
1215
Jeff Brown83c09682010-12-23 17:50:18 -08001216void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001217 dump.append(INDENT3 "Parameters:\n");
1218 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1219 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001220
1221 switch (mParameters.mode) {
1222 case Parameters::MODE_POINTER:
1223 dump.append(INDENT4 "Mode: pointer\n");
1224 break;
1225 case Parameters::MODE_NAVIGATION:
1226 dump.append(INDENT4 "Mode: navigation\n");
1227 break;
1228 default:
1229 assert(false);
1230 }
1231
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001232 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1233 toString(mParameters.orientationAware));
1234}
1235
Jeff Brown83c09682010-12-23 17:50:18 -08001236void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001237 mAccumulator.clear();
1238
Jeff Brown6328cdc2010-07-29 18:18:33 -07001239 mLocked.down = false;
1240 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001241}
1242
Jeff Brown83c09682010-12-23 17:50:18 -08001243void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001244 for (;;) {
1245 { // acquire lock
1246 AutoMutex _l(mLock);
1247
1248 if (! mLocked.down) {
1249 initializeLocked();
1250 break; // done
1251 }
1252 } // release lock
1253
Jeff Brown83c09682010-12-23 17:50:18 -08001254 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001255 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001256 mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001257 mAccumulator.btnMouse = false;
1258 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001259 }
1260
Jeff Brown6d0fec22010-07-23 21:28:06 -07001261 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001262}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001263
Jeff Brown83c09682010-12-23 17:50:18 -08001264void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001265 switch (rawEvent->type) {
1266 case EV_KEY:
1267 switch (rawEvent->scanCode) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001268 case BTN_LEFT:
1269 case BTN_RIGHT:
1270 case BTN_MIDDLE:
1271 case BTN_SIDE:
1272 case BTN_EXTRA:
1273 case BTN_FORWARD:
1274 case BTN_BACK:
1275 case BTN_TASK:
Jeff Brown6d0fec22010-07-23 21:28:06 -07001276 mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
1277 mAccumulator.btnMouse = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001278 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1279 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001280 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001281 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001282 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001283 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001284
Jeff Brown6d0fec22010-07-23 21:28:06 -07001285 case EV_REL:
1286 switch (rawEvent->scanCode) {
1287 case REL_X:
1288 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1289 mAccumulator.relX = rawEvent->value;
1290 break;
1291 case REL_Y:
1292 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1293 mAccumulator.relY = rawEvent->value;
1294 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001295 case REL_WHEEL:
1296 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1297 mAccumulator.relWheel = rawEvent->value;
1298 break;
1299 case REL_HWHEEL:
1300 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1301 mAccumulator.relHWheel = rawEvent->value;
1302 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001303 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001304 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001305
Jeff Brown6d0fec22010-07-23 21:28:06 -07001306 case EV_SYN:
1307 switch (rawEvent->scanCode) {
1308 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001309 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001310 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001311 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001312 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001313 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001314}
1315
Jeff Brown83c09682010-12-23 17:50:18 -08001316void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001317 uint32_t fields = mAccumulator.fields;
1318 if (fields == 0) {
1319 return; // no new state changes, so nothing to do
1320 }
1321
Jeff Brownd41cff22011-03-03 02:09:54 -08001322 int32_t motionEventAction;
1323 int32_t motionEventEdgeFlags;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001324 PointerCoords pointerCoords;
1325 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001326 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001327 { // acquire lock
1328 AutoMutex _l(mLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001329
Jeff Brown6328cdc2010-07-29 18:18:33 -07001330 bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
1331
1332 if (downChanged) {
1333 if (mAccumulator.btnMouse) {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001334 if (!mLocked.down) {
1335 mLocked.down = true;
1336 mLocked.downTime = when;
1337 } else {
1338 downChanged = false;
1339 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001340 } else {
Jeff Brown1c9d06e2011-01-14 17:24:16 -08001341 if (mLocked.down) {
1342 mLocked.down = false;
1343 } else {
1344 downChanged = false;
1345 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001346 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001347 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001348
Jeff Brown6328cdc2010-07-29 18:18:33 -07001349 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001350 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1351 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001352
Jeff Brown6328cdc2010-07-29 18:18:33 -07001353 if (downChanged) {
1354 motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Browncc0c1592011-02-19 05:07:28 -08001355 } else if (mLocked.down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001356 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001357 } else {
1358 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001359 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001360
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001361 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001362 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001363 // Rotate motion based on display orientation if needed.
1364 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1365 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001366 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1367 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001368 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001369 }
1370
1371 float temp;
1372 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001373 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001374 temp = deltaX;
1375 deltaX = deltaY;
1376 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001377 break;
1378
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001379 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001380 deltaX = -deltaX;
1381 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001382 break;
1383
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001384 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001385 temp = deltaX;
1386 deltaX = -deltaY;
1387 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001388 break;
1389 }
1390 }
Jeff Brown83c09682010-12-23 17:50:18 -08001391
Jeff Brown91c69ab2011-02-14 17:03:18 -08001392 pointerCoords.clear();
1393
Jeff Brownd41cff22011-03-03 02:09:54 -08001394 motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
1395
Jeff Brown83c09682010-12-23 17:50:18 -08001396 if (mPointerController != NULL) {
1397 mPointerController->move(deltaX, deltaY);
1398 if (downChanged) {
1399 mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
1400 }
Jeff Brown91c69ab2011-02-14 17:03:18 -08001401 float x, y;
1402 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001403 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1404 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brownd41cff22011-03-03 02:09:54 -08001405
1406 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
1407 float minX, minY, maxX, maxY;
1408 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1409 if (x <= minX) {
1410 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
1411 } else if (x >= maxX) {
1412 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
1413 }
1414 if (y <= minY) {
1415 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
1416 } else if (y >= maxY) {
1417 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
1418 }
1419 }
1420 }
Jeff Brown83c09682010-12-23 17:50:18 -08001421 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001422 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1423 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001424 }
1425
Jeff Brownebbd5d12011-02-17 13:01:34 -08001426 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, mLocked.down ? 1.0f : 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001427
1428 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001429 vscroll = mAccumulator.relWheel;
1430 } else {
1431 vscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001432 }
1433 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001434 hscroll = mAccumulator.relHWheel;
1435 } else {
1436 hscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001437 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001438 if (hscroll != 0 || vscroll != 0) {
1439 mPointerController->unfade();
1440 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001441 } // release lock
1442
Jeff Brown56194eb2011-03-02 19:23:13 -08001443 // Moving an external trackball or mouse should wake the device.
1444 // We don't do this for internal cursor devices to prevent them from waking up
1445 // the device in your pocket.
1446 // TODO: Use the input device configuration to control this behavior more finely.
1447 uint32_t policyFlags = 0;
1448 if (getDevice()->isExternal()) {
1449 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1450 }
1451
Jeff Brown6d0fec22010-07-23 21:28:06 -07001452 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001453 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08001454 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brownd41cff22011-03-03 02:09:54 -08001455 motionEventAction, 0, metaState, motionEventEdgeFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001456 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1457
1458 mAccumulator.clear();
Jeff Brown33bbfd22011-02-24 20:55:35 -08001459
1460 if (vscroll != 0 || hscroll != 0) {
1461 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1462 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1463
Jeff Brown56194eb2011-03-02 19:23:13 -08001464 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown33bbfd22011-02-24 20:55:35 -08001465 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1466 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1467 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001468}
1469
Jeff Brown83c09682010-12-23 17:50:18 -08001470int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001471 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1472 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1473 } else {
1474 return AKEY_STATE_UNKNOWN;
1475 }
1476}
1477
Jeff Brown05dc66a2011-03-02 14:41:58 -08001478void CursorInputMapper::fadePointer() {
1479 { // acquire lock
1480 AutoMutex _l(mLock);
1481 mPointerController->fade();
1482 } // release lock
1483}
1484
Jeff Brown6d0fec22010-07-23 21:28:06 -07001485
1486// --- TouchInputMapper ---
1487
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001488TouchInputMapper::TouchInputMapper(InputDevice* device) :
1489 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001490 mLocked.surfaceOrientation = -1;
1491 mLocked.surfaceWidth = -1;
1492 mLocked.surfaceHeight = -1;
1493
1494 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001495}
1496
1497TouchInputMapper::~TouchInputMapper() {
1498}
1499
1500uint32_t TouchInputMapper::getSources() {
Jeff Brown83c09682010-12-23 17:50:18 -08001501 return mSources;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001502}
1503
1504void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1505 InputMapper::populateDeviceInfo(info);
1506
Jeff Brown6328cdc2010-07-29 18:18:33 -07001507 { // acquire lock
1508 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001509
Jeff Brown6328cdc2010-07-29 18:18:33 -07001510 // Ensure surface information is up to date so that orientation changes are
1511 // noticed immediately.
1512 configureSurfaceLocked();
1513
Jeff Brown6f2fba42011-02-19 01:08:02 -08001514 info->addMotionRange(AMOTION_EVENT_AXIS_X, mLocked.orientedRanges.x);
1515 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001516
1517 if (mLocked.orientedRanges.havePressure) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001518 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
Jeff Brown8d608662010-08-30 03:02:23 -07001519 mLocked.orientedRanges.pressure);
1520 }
1521
1522 if (mLocked.orientedRanges.haveSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001523 info->addMotionRange(AMOTION_EVENT_AXIS_SIZE,
Jeff Brown8d608662010-08-30 03:02:23 -07001524 mLocked.orientedRanges.size);
1525 }
1526
Jeff Brownc6d282b2010-10-14 21:42:15 -07001527 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001528 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001529 mLocked.orientedRanges.touchMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001530 info->addMotionRange(AMOTION_EVENT_AXIS_TOUCH_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001531 mLocked.orientedRanges.touchMinor);
1532 }
1533
Jeff Brownc6d282b2010-10-14 21:42:15 -07001534 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001535 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MAJOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001536 mLocked.orientedRanges.toolMajor);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001537 info->addMotionRange(AMOTION_EVENT_AXIS_TOOL_MINOR,
Jeff Brown8d608662010-08-30 03:02:23 -07001538 mLocked.orientedRanges.toolMinor);
1539 }
1540
1541 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08001542 info->addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION,
Jeff Brown8d608662010-08-30 03:02:23 -07001543 mLocked.orientedRanges.orientation);
1544 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001545 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001546}
1547
Jeff Brownef3d7e82010-09-30 14:33:04 -07001548void TouchInputMapper::dump(String8& dump) {
1549 { // acquire lock
1550 AutoMutex _l(mLock);
1551 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001552 dumpParameters(dump);
1553 dumpVirtualKeysLocked(dump);
1554 dumpRawAxes(dump);
1555 dumpCalibration(dump);
1556 dumpSurfaceLocked(dump);
Jeff Brown511ee5f2010-10-18 13:32:20 -07001557 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001558 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1559 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1560 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1561 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1562 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1563 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1564 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1565 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1566 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1567 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1568 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
1569 dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001570 } // release lock
1571}
1572
Jeff Brown6328cdc2010-07-29 18:18:33 -07001573void TouchInputMapper::initializeLocked() {
1574 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001575 mLastTouch.clear();
1576 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001577
1578 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1579 mAveragingTouchFilter.historyStart[i] = 0;
1580 mAveragingTouchFilter.historyEnd[i] = 0;
1581 }
1582
1583 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001584
1585 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001586
1587 mLocked.orientedRanges.havePressure = false;
1588 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001589 mLocked.orientedRanges.haveTouchSize = false;
1590 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001591 mLocked.orientedRanges.haveOrientation = false;
1592}
1593
Jeff Brown6d0fec22010-07-23 21:28:06 -07001594void TouchInputMapper::configure() {
1595 InputMapper::configure();
1596
1597 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001598 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001599
Jeff Brown83c09682010-12-23 17:50:18 -08001600 // Configure sources.
1601 switch (mParameters.deviceType) {
1602 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1603 mSources = AINPUT_SOURCE_TOUCHSCREEN;
1604 break;
1605 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1606 mSources = AINPUT_SOURCE_TOUCHPAD;
1607 break;
1608 default:
1609 assert(false);
1610 }
1611
Jeff Brown6d0fec22010-07-23 21:28:06 -07001612 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001613 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001614
1615 // Prepare input device calibration.
1616 parseCalibration();
1617 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001618
Jeff Brown6328cdc2010-07-29 18:18:33 -07001619 { // acquire lock
1620 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001621
Jeff Brown8d608662010-08-30 03:02:23 -07001622 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001623 configureSurfaceLocked();
1624 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001625}
1626
Jeff Brown8d608662010-08-30 03:02:23 -07001627void TouchInputMapper::configureParameters() {
1628 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1629 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1630 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001631 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001632
1633 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001634 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001635 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1636 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001637 if (deviceTypeString == "touchScreen") {
1638 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1639 } else if (deviceTypeString != "touchPad") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001640 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1641 }
1642 }
1643 bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1644
1645 mParameters.orientationAware = isTouchScreen;
1646 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1647 mParameters.orientationAware);
1648
1649 mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001650}
1651
Jeff Brownef3d7e82010-09-30 14:33:04 -07001652void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001653 dump.append(INDENT3 "Parameters:\n");
1654
1655 switch (mParameters.deviceType) {
1656 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1657 dump.append(INDENT4 "DeviceType: touchScreen\n");
1658 break;
1659 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1660 dump.append(INDENT4 "DeviceType: touchPad\n");
1661 break;
1662 default:
1663 assert(false);
1664 }
1665
1666 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1667 mParameters.associatedDisplayId);
1668 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1669 toString(mParameters.orientationAware));
1670
1671 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001672 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001673 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001674 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001675 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001676 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001677}
1678
Jeff Brown8d608662010-08-30 03:02:23 -07001679void TouchInputMapper::configureRawAxes() {
1680 mRawAxes.x.clear();
1681 mRawAxes.y.clear();
1682 mRawAxes.pressure.clear();
1683 mRawAxes.touchMajor.clear();
1684 mRawAxes.touchMinor.clear();
1685 mRawAxes.toolMajor.clear();
1686 mRawAxes.toolMinor.clear();
1687 mRawAxes.orientation.clear();
1688}
1689
Jeff Brownef3d7e82010-09-30 14:33:04 -07001690void TouchInputMapper::dumpRawAxes(String8& dump) {
1691 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001692 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1693 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1694 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1695 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1696 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1697 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1698 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1699 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001700}
1701
Jeff Brown6328cdc2010-07-29 18:18:33 -07001702bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brownd41cff22011-03-03 02:09:54 -08001703 // Ensure we have valid X and Y axes.
1704 if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
1705 LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
1706 "The device will be inoperable.", getDeviceName().string());
1707 return false;
1708 }
1709
Jeff Brown6d0fec22010-07-23 21:28:06 -07001710 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001711 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brownd41cff22011-03-03 02:09:54 -08001712 int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
1713 int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001714
1715 if (mParameters.associatedDisplayId >= 0) {
1716 bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
1717 bool wantOrientation = mParameters.orientationAware;
1718
Jeff Brown6328cdc2010-07-29 18:18:33 -07001719 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001720 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1721 wantSize ? &width : NULL, wantSize ? &height : NULL,
1722 wantOrientation ? &orientation : NULL)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001723 return false;
1724 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001725 }
1726
Jeff Brown6328cdc2010-07-29 18:18:33 -07001727 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001728 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001729 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001730 }
1731
Jeff Brown6328cdc2010-07-29 18:18:33 -07001732 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001733 if (sizeChanged) {
Jeff Brown90655042010-12-02 13:50:46 -08001734 LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001735 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001736
Jeff Brown6328cdc2010-07-29 18:18:33 -07001737 mLocked.surfaceWidth = width;
1738 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001739
Jeff Brown8d608662010-08-30 03:02:23 -07001740 // Configure X and Y factors.
Jeff Brownd41cff22011-03-03 02:09:54 -08001741 mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
1742 mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
1743 mLocked.xPrecision = 1.0f / mLocked.xScale;
1744 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001745
Jeff Brownd41cff22011-03-03 02:09:54 -08001746 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001747
Jeff Brown8d608662010-08-30 03:02:23 -07001748 // Scale factor for terms that are not oriented in a particular axis.
1749 // If the pixels are square then xScale == yScale otherwise we fake it
1750 // by choosing an average.
1751 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001752
Jeff Brown8d608662010-08-30 03:02:23 -07001753 // Size of diagonal axis.
1754 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001755
Jeff Brown8d608662010-08-30 03:02:23 -07001756 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001757 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1758 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001759 mLocked.orientedRanges.touchMajor.min = 0;
1760 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1761 mLocked.orientedRanges.touchMajor.flat = 0;
1762 mLocked.orientedRanges.touchMajor.fuzz = 0;
1763 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
1764 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001765
Jeff Brown8d608662010-08-30 03:02:23 -07001766 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001767 mLocked.toolSizeLinearScale = 0;
1768 mLocked.toolSizeLinearBias = 0;
1769 mLocked.toolSizeAreaScale = 0;
1770 mLocked.toolSizeAreaBias = 0;
1771 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1772 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1773 if (mCalibration.haveToolSizeLinearScale) {
1774 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001775 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001776 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001777 / mRawAxes.toolMajor.maxValue;
1778 }
1779
Jeff Brownc6d282b2010-10-14 21:42:15 -07001780 if (mCalibration.haveToolSizeLinearBias) {
1781 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1782 }
1783 } else if (mCalibration.toolSizeCalibration ==
1784 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1785 if (mCalibration.haveToolSizeLinearScale) {
1786 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1787 } else {
1788 mLocked.toolSizeLinearScale = min(width, height);
1789 }
1790
1791 if (mCalibration.haveToolSizeLinearBias) {
1792 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1793 }
1794
1795 if (mCalibration.haveToolSizeAreaScale) {
1796 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1797 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1798 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1799 }
1800
1801 if (mCalibration.haveToolSizeAreaBias) {
1802 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001803 }
1804 }
1805
Jeff Brownc6d282b2010-10-14 21:42:15 -07001806 mLocked.orientedRanges.haveToolSize = true;
Jeff Brown8d608662010-08-30 03:02:23 -07001807 mLocked.orientedRanges.toolMajor.min = 0;
1808 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1809 mLocked.orientedRanges.toolMajor.flat = 0;
1810 mLocked.orientedRanges.toolMajor.fuzz = 0;
1811 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
1812 }
1813
1814 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001815 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001816 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1817 RawAbsoluteAxisInfo rawPressureAxis;
1818 switch (mCalibration.pressureSource) {
1819 case Calibration::PRESSURE_SOURCE_PRESSURE:
1820 rawPressureAxis = mRawAxes.pressure;
1821 break;
1822 case Calibration::PRESSURE_SOURCE_TOUCH:
1823 rawPressureAxis = mRawAxes.touchMajor;
1824 break;
1825 default:
1826 rawPressureAxis.clear();
1827 }
1828
Jeff Brown8d608662010-08-30 03:02:23 -07001829 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1830 || mCalibration.pressureCalibration
1831 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1832 if (mCalibration.havePressureScale) {
1833 mLocked.pressureScale = mCalibration.pressureScale;
1834 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1835 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1836 }
1837 }
1838
1839 mLocked.orientedRanges.havePressure = true;
1840 mLocked.orientedRanges.pressure.min = 0;
1841 mLocked.orientedRanges.pressure.max = 1.0;
1842 mLocked.orientedRanges.pressure.flat = 0;
1843 mLocked.orientedRanges.pressure.fuzz = 0;
1844 }
1845
1846 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001847 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001848 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001849 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1850 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1851 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1852 }
1853 }
1854
1855 mLocked.orientedRanges.haveSize = true;
1856 mLocked.orientedRanges.size.min = 0;
1857 mLocked.orientedRanges.size.max = 1.0;
1858 mLocked.orientedRanges.size.flat = 0;
1859 mLocked.orientedRanges.size.fuzz = 0;
1860 }
1861
1862 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001863 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001864 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001865 if (mCalibration.orientationCalibration
1866 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1867 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1868 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1869 }
1870 }
1871
1872 mLocked.orientedRanges.orientation.min = - M_PI_2;
1873 mLocked.orientedRanges.orientation.max = M_PI_2;
1874 mLocked.orientedRanges.orientation.flat = 0;
1875 mLocked.orientedRanges.orientation.fuzz = 0;
1876 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001877 }
1878
1879 if (orientationChanged || sizeChanged) {
Jeff Brownd41cff22011-03-03 02:09:54 -08001880 // Compute oriented surface dimensions, precision, scales and ranges.
1881 // Note that the maximum value reported is an inclusive maximum value so it is one
1882 // unit less than the total width or height of surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001883 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001884 case DISPLAY_ORIENTATION_90:
1885 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001886 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1887 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
Jeff Brownd41cff22011-03-03 02:09:54 -08001888
Jeff Brown6328cdc2010-07-29 18:18:33 -07001889 mLocked.orientedXPrecision = mLocked.yPrecision;
1890 mLocked.orientedYPrecision = mLocked.xPrecision;
Jeff Brownd41cff22011-03-03 02:09:54 -08001891
1892 mLocked.orientedRanges.x.min = 0;
1893 mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
1894 * mLocked.yScale;
1895 mLocked.orientedRanges.x.flat = 0;
1896 mLocked.orientedRanges.x.fuzz = mLocked.yScale;
1897
1898 mLocked.orientedRanges.y.min = 0;
1899 mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
1900 * mLocked.xScale;
1901 mLocked.orientedRanges.y.flat = 0;
1902 mLocked.orientedRanges.y.fuzz = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001903 break;
Jeff Brownd41cff22011-03-03 02:09:54 -08001904
Jeff Brown6d0fec22010-07-23 21:28:06 -07001905 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001906 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1907 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
Jeff Brownd41cff22011-03-03 02:09:54 -08001908
Jeff Brown6328cdc2010-07-29 18:18:33 -07001909 mLocked.orientedXPrecision = mLocked.xPrecision;
1910 mLocked.orientedYPrecision = mLocked.yPrecision;
Jeff Brownd41cff22011-03-03 02:09:54 -08001911
1912 mLocked.orientedRanges.x.min = 0;
1913 mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
1914 * mLocked.xScale;
1915 mLocked.orientedRanges.x.flat = 0;
1916 mLocked.orientedRanges.x.fuzz = mLocked.xScale;
1917
1918 mLocked.orientedRanges.y.min = 0;
1919 mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
1920 * mLocked.yScale;
1921 mLocked.orientedRanges.y.flat = 0;
1922 mLocked.orientedRanges.y.fuzz = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001923 break;
1924 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001925 }
1926
1927 return true;
1928}
1929
Jeff Brownef3d7e82010-09-30 14:33:04 -07001930void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
1931 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
1932 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
1933 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07001934}
1935
Jeff Brown6328cdc2010-07-29 18:18:33 -07001936void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07001937 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08001938 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001939
Jeff Brown6328cdc2010-07-29 18:18:33 -07001940 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001941
Jeff Brown6328cdc2010-07-29 18:18:33 -07001942 if (virtualKeyDefinitions.size() == 0) {
1943 return;
1944 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001945
Jeff Brown6328cdc2010-07-29 18:18:33 -07001946 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1947
Jeff Brown8d608662010-08-30 03:02:23 -07001948 int32_t touchScreenLeft = mRawAxes.x.minValue;
1949 int32_t touchScreenTop = mRawAxes.y.minValue;
Jeff Brownd41cff22011-03-03 02:09:54 -08001950 int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
1951 int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001952
1953 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07001954 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07001955 virtualKeyDefinitions[i];
1956
1957 mLocked.virtualKeys.add();
1958 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
1959
1960 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1961 int32_t keyCode;
1962 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001963 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07001964 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07001965 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
1966 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001967 mLocked.virtualKeys.pop(); // drop the key
1968 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001969 }
1970
Jeff Brown6328cdc2010-07-29 18:18:33 -07001971 virtualKey.keyCode = keyCode;
1972 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001973
Jeff Brown6328cdc2010-07-29 18:18:33 -07001974 // convert the key definition's display coordinates into touch coordinates for a hit box
1975 int32_t halfWidth = virtualKeyDefinition.width / 2;
1976 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001977
Jeff Brown6328cdc2010-07-29 18:18:33 -07001978 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1979 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1980 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1981 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
1982 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1983 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
1984 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1985 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brownef3d7e82010-09-30 14:33:04 -07001986 }
1987}
1988
1989void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
1990 if (!mLocked.virtualKeys.isEmpty()) {
1991 dump.append(INDENT3 "Virtual Keys:\n");
1992
1993 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
1994 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
1995 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
1996 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
1997 i, virtualKey.scanCode, virtualKey.keyCode,
1998 virtualKey.hitLeft, virtualKey.hitRight,
1999 virtualKey.hitTop, virtualKey.hitBottom);
2000 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002001 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002002}
2003
Jeff Brown8d608662010-08-30 03:02:23 -07002004void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002005 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07002006 Calibration& out = mCalibration;
2007
Jeff Brownc6d282b2010-10-14 21:42:15 -07002008 // Touch Size
2009 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2010 String8 touchSizeCalibrationString;
2011 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2012 if (touchSizeCalibrationString == "none") {
2013 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2014 } else if (touchSizeCalibrationString == "geometric") {
2015 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2016 } else if (touchSizeCalibrationString == "pressure") {
2017 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2018 } else if (touchSizeCalibrationString != "default") {
2019 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2020 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002021 }
2022 }
2023
Jeff Brownc6d282b2010-10-14 21:42:15 -07002024 // Tool Size
2025 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2026 String8 toolSizeCalibrationString;
2027 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2028 if (toolSizeCalibrationString == "none") {
2029 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2030 } else if (toolSizeCalibrationString == "geometric") {
2031 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2032 } else if (toolSizeCalibrationString == "linear") {
2033 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2034 } else if (toolSizeCalibrationString == "area") {
2035 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2036 } else if (toolSizeCalibrationString != "default") {
2037 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2038 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002039 }
2040 }
2041
Jeff Brownc6d282b2010-10-14 21:42:15 -07002042 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2043 out.toolSizeLinearScale);
2044 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2045 out.toolSizeLinearBias);
2046 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2047 out.toolSizeAreaScale);
2048 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2049 out.toolSizeAreaBias);
2050 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2051 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07002052
2053 // Pressure
2054 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2055 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002056 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002057 if (pressureCalibrationString == "none") {
2058 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2059 } else if (pressureCalibrationString == "physical") {
2060 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2061 } else if (pressureCalibrationString == "amplitude") {
2062 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2063 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002064 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002065 pressureCalibrationString.string());
2066 }
2067 }
2068
2069 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2070 String8 pressureSourceString;
2071 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2072 if (pressureSourceString == "pressure") {
2073 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2074 } else if (pressureSourceString == "touch") {
2075 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2076 } else if (pressureSourceString != "default") {
2077 LOGW("Invalid value for touch.pressure.source: '%s'",
2078 pressureSourceString.string());
2079 }
2080 }
2081
2082 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2083 out.pressureScale);
2084
2085 // Size
2086 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2087 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002088 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002089 if (sizeCalibrationString == "none") {
2090 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2091 } else if (sizeCalibrationString == "normalized") {
2092 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2093 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002094 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002095 sizeCalibrationString.string());
2096 }
2097 }
2098
2099 // Orientation
2100 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2101 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002102 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002103 if (orientationCalibrationString == "none") {
2104 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2105 } else if (orientationCalibrationString == "interpolated") {
2106 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002107 } else if (orientationCalibrationString == "vector") {
2108 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002109 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002110 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002111 orientationCalibrationString.string());
2112 }
2113 }
2114}
2115
2116void TouchInputMapper::resolveCalibration() {
2117 // Pressure
2118 switch (mCalibration.pressureSource) {
2119 case Calibration::PRESSURE_SOURCE_DEFAULT:
2120 if (mRawAxes.pressure.valid) {
2121 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2122 } else if (mRawAxes.touchMajor.valid) {
2123 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2124 }
2125 break;
2126
2127 case Calibration::PRESSURE_SOURCE_PRESSURE:
2128 if (! mRawAxes.pressure.valid) {
2129 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2130 "the pressure axis is not available.");
2131 }
2132 break;
2133
2134 case Calibration::PRESSURE_SOURCE_TOUCH:
2135 if (! mRawAxes.touchMajor.valid) {
2136 LOGW("Calibration property touch.pressure.source is 'touch' but "
2137 "the touchMajor axis is not available.");
2138 }
2139 break;
2140
2141 default:
2142 break;
2143 }
2144
2145 switch (mCalibration.pressureCalibration) {
2146 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2147 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2148 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2149 } else {
2150 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2151 }
2152 break;
2153
2154 default:
2155 break;
2156 }
2157
Jeff Brownc6d282b2010-10-14 21:42:15 -07002158 // Tool Size
2159 switch (mCalibration.toolSizeCalibration) {
2160 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002161 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002162 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002163 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002164 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002165 }
2166 break;
2167
2168 default:
2169 break;
2170 }
2171
Jeff Brownc6d282b2010-10-14 21:42:15 -07002172 // Touch Size
2173 switch (mCalibration.touchSizeCalibration) {
2174 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002175 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002176 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2177 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002178 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002179 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002180 }
2181 break;
2182
2183 default:
2184 break;
2185 }
2186
2187 // Size
2188 switch (mCalibration.sizeCalibration) {
2189 case Calibration::SIZE_CALIBRATION_DEFAULT:
2190 if (mRawAxes.toolMajor.valid) {
2191 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2192 } else {
2193 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2194 }
2195 break;
2196
2197 default:
2198 break;
2199 }
2200
2201 // Orientation
2202 switch (mCalibration.orientationCalibration) {
2203 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2204 if (mRawAxes.orientation.valid) {
2205 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2206 } else {
2207 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2208 }
2209 break;
2210
2211 default:
2212 break;
2213 }
2214}
2215
Jeff Brownef3d7e82010-09-30 14:33:04 -07002216void TouchInputMapper::dumpCalibration(String8& dump) {
2217 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002218
Jeff Brownc6d282b2010-10-14 21:42:15 -07002219 // Touch Size
2220 switch (mCalibration.touchSizeCalibration) {
2221 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2222 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002223 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002224 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2225 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002226 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002227 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2228 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002229 break;
2230 default:
2231 assert(false);
2232 }
2233
Jeff Brownc6d282b2010-10-14 21:42:15 -07002234 // Tool Size
2235 switch (mCalibration.toolSizeCalibration) {
2236 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2237 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002238 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002239 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2240 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002241 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002242 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2243 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2244 break;
2245 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2246 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002247 break;
2248 default:
2249 assert(false);
2250 }
2251
Jeff Brownc6d282b2010-10-14 21:42:15 -07002252 if (mCalibration.haveToolSizeLinearScale) {
2253 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2254 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002255 }
2256
Jeff Brownc6d282b2010-10-14 21:42:15 -07002257 if (mCalibration.haveToolSizeLinearBias) {
2258 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2259 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002260 }
2261
Jeff Brownc6d282b2010-10-14 21:42:15 -07002262 if (mCalibration.haveToolSizeAreaScale) {
2263 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2264 mCalibration.toolSizeAreaScale);
2265 }
2266
2267 if (mCalibration.haveToolSizeAreaBias) {
2268 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2269 mCalibration.toolSizeAreaBias);
2270 }
2271
2272 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002273 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002274 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002275 }
2276
2277 // Pressure
2278 switch (mCalibration.pressureCalibration) {
2279 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002280 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002281 break;
2282 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002283 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002284 break;
2285 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002286 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002287 break;
2288 default:
2289 assert(false);
2290 }
2291
2292 switch (mCalibration.pressureSource) {
2293 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002294 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002295 break;
2296 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002297 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002298 break;
2299 case Calibration::PRESSURE_SOURCE_DEFAULT:
2300 break;
2301 default:
2302 assert(false);
2303 }
2304
2305 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002306 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2307 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002308 }
2309
2310 // Size
2311 switch (mCalibration.sizeCalibration) {
2312 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002313 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002314 break;
2315 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002316 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002317 break;
2318 default:
2319 assert(false);
2320 }
2321
2322 // Orientation
2323 switch (mCalibration.orientationCalibration) {
2324 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002325 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002326 break;
2327 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002328 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002329 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002330 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2331 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2332 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002333 default:
2334 assert(false);
2335 }
2336}
2337
Jeff Brown6d0fec22010-07-23 21:28:06 -07002338void TouchInputMapper::reset() {
2339 // Synthesize touch up event if touch is currently down.
2340 // This will also take care of finishing virtual key processing if needed.
2341 if (mLastTouch.pointerCount != 0) {
2342 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2343 mCurrentTouch.clear();
2344 syncTouch(when, true);
2345 }
2346
Jeff Brown6328cdc2010-07-29 18:18:33 -07002347 { // acquire lock
2348 AutoMutex _l(mLock);
2349 initializeLocked();
2350 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002351
Jeff Brown6328cdc2010-07-29 18:18:33 -07002352 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002353}
2354
2355void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002356 // Preprocess pointer data.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002357 if (mParameters.useBadTouchFilter) {
2358 if (applyBadTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002359 havePointerIds = false;
2360 }
2361 }
2362
Jeff Brown6d0fec22010-07-23 21:28:06 -07002363 if (mParameters.useJumpyTouchFilter) {
2364 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002365 havePointerIds = false;
2366 }
2367 }
2368
2369 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002370 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002371 }
2372
Jeff Brown6d0fec22010-07-23 21:28:06 -07002373 TouchData temp;
2374 TouchData* savedTouch;
2375 if (mParameters.useAveragingTouchFilter) {
2376 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002377 savedTouch = & temp;
2378
Jeff Brown6d0fec22010-07-23 21:28:06 -07002379 applyAveragingTouchFilter();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002380 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002381 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002382 }
2383
Jeff Brown56194eb2011-03-02 19:23:13 -08002384 uint32_t policyFlags = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -08002385 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brown56194eb2011-03-02 19:23:13 -08002386 // Hide the pointer on an initial down.
Jeff Brown05dc66a2011-03-02 14:41:58 -08002387 getContext()->fadePointer();
Jeff Brown56194eb2011-03-02 19:23:13 -08002388
2389 // Initial downs on external touch devices should wake the device.
2390 // We don't do this for internal touch screens to prevent them from waking
2391 // up in your pocket.
2392 // TODO: Use the input device configuration to control this behavior more finely.
2393 if (getDevice()->isExternal()) {
2394 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2395 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002396 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002397
Jeff Brown05dc66a2011-03-02 14:41:58 -08002398 // Process touches and virtual keys.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002399 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2400 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownfe508922011-01-18 15:10:10 -08002401 detectGestures(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002402 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002403 }
2404
Jeff Brown6328cdc2010-07-29 18:18:33 -07002405 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002406 if (touchResult == DROP_STROKE) {
2407 mLastTouch.clear();
2408 } else {
2409 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002410 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002411}
2412
Jeff Brown6d0fec22010-07-23 21:28:06 -07002413TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2414 nsecs_t when, uint32_t policyFlags) {
2415 int32_t keyEventAction, keyEventFlags;
2416 int32_t keyCode, scanCode, downTime;
2417 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002418
Jeff Brown6328cdc2010-07-29 18:18:33 -07002419 { // acquire lock
2420 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002421
Jeff Brown6328cdc2010-07-29 18:18:33 -07002422 // Update surface size and orientation, including virtual key positions.
2423 if (! configureSurfaceLocked()) {
2424 return DROP_STROKE;
2425 }
2426
2427 // Check for virtual key press.
2428 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002429 if (mCurrentTouch.pointerCount == 0) {
2430 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002431 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002432#if DEBUG_VIRTUAL_KEYS
2433 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002434 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002435#endif
2436 keyEventAction = AKEY_EVENT_ACTION_UP;
2437 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2438 touchResult = SKIP_TOUCH;
2439 goto DispatchVirtualKey;
2440 }
2441
2442 if (mCurrentTouch.pointerCount == 1) {
2443 int32_t x = mCurrentTouch.pointers[0].x;
2444 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002445 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2446 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002447 // Pointer is still within the space of the virtual key.
2448 return SKIP_TOUCH;
2449 }
2450 }
2451
2452 // Pointer left virtual key area or another pointer also went down.
2453 // Send key cancellation and drop the stroke so subsequent motions will be
2454 // considered fresh downs. This is useful when the user swipes away from the
2455 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002456 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002457#if DEBUG_VIRTUAL_KEYS
2458 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002459 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002460#endif
2461 keyEventAction = AKEY_EVENT_ACTION_UP;
2462 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2463 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002464
2465 // Check whether the pointer moved inside the display area where we should
2466 // start a new stroke.
2467 int32_t x = mCurrentTouch.pointers[0].x;
2468 int32_t y = mCurrentTouch.pointers[0].y;
2469 if (isPointInsideSurfaceLocked(x, y)) {
2470 mLastTouch.clear();
2471 touchResult = DISPATCH_TOUCH;
2472 } else {
2473 touchResult = DROP_STROKE;
2474 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002475 } else {
2476 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2477 // Pointer just went down. Handle off-screen touches, if needed.
2478 int32_t x = mCurrentTouch.pointers[0].x;
2479 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002480 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002481 // If exactly one pointer went down, check for virtual key hit.
2482 // Otherwise we will drop the entire stroke.
2483 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002484 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002485 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002486 if (mContext->shouldDropVirtualKey(when, getDevice(),
2487 virtualKey->keyCode, virtualKey->scanCode)) {
2488 return DROP_STROKE;
2489 }
2490
Jeff Brown6328cdc2010-07-29 18:18:33 -07002491 mLocked.currentVirtualKey.down = true;
2492 mLocked.currentVirtualKey.downTime = when;
2493 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2494 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002495#if DEBUG_VIRTUAL_KEYS
2496 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002497 mLocked.currentVirtualKey.keyCode,
2498 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002499#endif
2500 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2501 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2502 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2503 touchResult = SKIP_TOUCH;
2504 goto DispatchVirtualKey;
2505 }
2506 }
2507 return DROP_STROKE;
2508 }
2509 }
2510 return DISPATCH_TOUCH;
2511 }
2512
2513 DispatchVirtualKey:
2514 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002515 keyCode = mLocked.currentVirtualKey.keyCode;
2516 scanCode = mLocked.currentVirtualKey.scanCode;
2517 downTime = mLocked.currentVirtualKey.downTime;
2518 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002519
2520 // Dispatch virtual key.
2521 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002522 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002523 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2524 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2525 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002526}
2527
Jeff Brownfe508922011-01-18 15:10:10 -08002528void TouchInputMapper::detectGestures(nsecs_t when) {
2529 // Disable all virtual key touches that happen within a short time interval of the
2530 // most recent touch. The idea is to filter out stray virtual key presses when
2531 // interacting with the touch screen.
2532 //
2533 // Problems we're trying to solve:
2534 //
2535 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2536 // virtual key area that is implemented by a separate touch panel and accidentally
2537 // triggers a virtual key.
2538 //
2539 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2540 // area and accidentally triggers a virtual key. This often happens when virtual keys
2541 // are layed out below the screen near to where the on screen keyboard's space bar
2542 // is displayed.
2543 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2544 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2545 }
2546}
2547
Jeff Brown6d0fec22010-07-23 21:28:06 -07002548void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2549 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2550 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002551 if (currentPointerCount == 0 && lastPointerCount == 0) {
2552 return; // nothing to do!
2553 }
2554
Jeff Brown6d0fec22010-07-23 21:28:06 -07002555 BitSet32 currentIdBits = mCurrentTouch.idBits;
2556 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002557
2558 if (currentIdBits == lastIdBits) {
2559 // No pointer id changes so this is a move event.
2560 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002561 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002562 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002563 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002564 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002565 // There may be pointers going up and pointers going down and pointers moving
2566 // all at the same time.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002567 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2568 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2569 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002570 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002571
Jeff Brownc3db8582010-10-20 15:33:38 -07002572 // Produce an intermediate representation of the touch data that consists of the
2573 // old location of pointers that have just gone up and the new location of pointers that
2574 // have just moved but omits the location of pointers that have just gone down.
2575 TouchData interimTouch;
2576 interimTouch.copyFrom(mLastTouch);
2577
2578 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2579 bool moveNeeded = false;
2580 while (!moveIdBits.isEmpty()) {
2581 uint32_t moveId = moveIdBits.firstMarkedBit();
2582 moveIdBits.clearBit(moveId);
2583
2584 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2585 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2586 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2587 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2588 moveNeeded = true;
2589 }
2590 }
2591
2592 // Dispatch pointer up events using the interim pointer locations.
2593 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002594 uint32_t upId = upIdBits.firstMarkedBit();
2595 upIdBits.clearBit(upId);
2596 BitSet32 oldActiveIdBits = activeIdBits;
2597 activeIdBits.clearBit(upId);
2598
2599 int32_t motionEventAction;
2600 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002601 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002602 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002603 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002604 }
2605
Jeff Brownc3db8582010-10-20 15:33:38 -07002606 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002607 oldActiveIdBits, upId, pointerCount, motionEventAction);
2608 pointerCount -= 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002609 }
2610
Jeff Brownc3db8582010-10-20 15:33:38 -07002611 // Dispatch move events if any of the remaining pointers moved from their old locations.
2612 // Although applications receive new locations as part of individual pointer up
2613 // events, they do not generally handle them except when presented in a move event.
2614 if (moveNeeded) {
2615 dispatchTouch(when, policyFlags, &mCurrentTouch,
2616 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2617 }
2618
2619 // Dispatch pointer down events using the new pointer locations.
2620 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002621 uint32_t downId = downIdBits.firstMarkedBit();
2622 downIdBits.clearBit(downId);
2623 BitSet32 oldActiveIdBits = activeIdBits;
2624 activeIdBits.markBit(downId);
2625
2626 int32_t motionEventAction;
2627 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002628 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002629 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002630 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002631 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002632 }
2633
Jeff Brown8d608662010-08-30 03:02:23 -07002634 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002635 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002636 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002637 }
2638 }
2639}
2640
Jeff Brown6d0fec22010-07-23 21:28:06 -07002641void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002642 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002643 int32_t motionEventAction) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002644 int32_t pointerIds[MAX_POINTERS];
2645 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brownd41cff22011-03-03 02:09:54 -08002646 int32_t motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002647 float xPrecision, yPrecision;
2648
2649 { // acquire lock
2650 AutoMutex _l(mLock);
2651
2652 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
2653 // display coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002654 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002655 uint32_t id = idBits.firstMarkedBit();
2656 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002657 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002658
Jeff Brown8d608662010-08-30 03:02:23 -07002659 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002660
Jeff Brown8d608662010-08-30 03:02:23 -07002661 // ToolMajor and ToolMinor
2662 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002663 switch (mCalibration.toolSizeCalibration) {
2664 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002665 toolMajor = in.toolMajor * mLocked.geometricScale;
2666 if (mRawAxes.toolMinor.valid) {
2667 toolMinor = in.toolMinor * mLocked.geometricScale;
2668 } else {
2669 toolMinor = toolMajor;
2670 }
2671 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002672 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002673 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002674 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002675 : 0;
2676 if (mRawAxes.toolMinor.valid) {
2677 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002678 ? in.toolMinor * mLocked.toolSizeLinearScale
2679 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002680 : 0;
2681 } else {
2682 toolMinor = toolMajor;
2683 }
2684 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002685 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2686 if (in.toolMajor != 0) {
2687 float diameter = sqrtf(in.toolMajor
2688 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2689 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2690 } else {
2691 toolMajor = 0;
2692 }
2693 toolMinor = toolMajor;
2694 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002695 default:
2696 toolMajor = 0;
2697 toolMinor = 0;
2698 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002699 }
2700
Jeff Brownc6d282b2010-10-14 21:42:15 -07002701 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002702 toolMajor /= pointerCount;
2703 toolMinor /= pointerCount;
2704 }
2705
2706 // Pressure
2707 float rawPressure;
2708 switch (mCalibration.pressureSource) {
2709 case Calibration::PRESSURE_SOURCE_PRESSURE:
2710 rawPressure = in.pressure;
2711 break;
2712 case Calibration::PRESSURE_SOURCE_TOUCH:
2713 rawPressure = in.touchMajor;
2714 break;
2715 default:
2716 rawPressure = 0;
2717 }
2718
2719 float pressure;
2720 switch (mCalibration.pressureCalibration) {
2721 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2722 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2723 pressure = rawPressure * mLocked.pressureScale;
2724 break;
2725 default:
2726 pressure = 1;
2727 break;
2728 }
2729
2730 // TouchMajor and TouchMinor
2731 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002732 switch (mCalibration.touchSizeCalibration) {
2733 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002734 touchMajor = in.touchMajor * mLocked.geometricScale;
2735 if (mRawAxes.touchMinor.valid) {
2736 touchMinor = in.touchMinor * mLocked.geometricScale;
2737 } else {
2738 touchMinor = touchMajor;
2739 }
2740 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002741 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002742 touchMajor = toolMajor * pressure;
2743 touchMinor = toolMinor * pressure;
2744 break;
2745 default:
2746 touchMajor = 0;
2747 touchMinor = 0;
2748 break;
2749 }
2750
2751 if (touchMajor > toolMajor) {
2752 touchMajor = toolMajor;
2753 }
2754 if (touchMinor > toolMinor) {
2755 touchMinor = toolMinor;
2756 }
2757
2758 // Size
2759 float size;
2760 switch (mCalibration.sizeCalibration) {
2761 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2762 float rawSize = mRawAxes.toolMinor.valid
2763 ? avg(in.toolMajor, in.toolMinor)
2764 : in.toolMajor;
2765 size = rawSize * mLocked.sizeScale;
2766 break;
2767 }
2768 default:
2769 size = 0;
2770 break;
2771 }
2772
2773 // Orientation
2774 float orientation;
2775 switch (mCalibration.orientationCalibration) {
2776 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2777 orientation = in.orientation * mLocked.orientationScale;
2778 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002779 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2780 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2781 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2782 if (c1 != 0 || c2 != 0) {
2783 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002784 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2785 touchMajor *= scale;
2786 touchMinor /= scale;
2787 toolMajor *= scale;
2788 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002789 } else {
2790 orientation = 0;
2791 }
2792 break;
2793 }
Jeff Brown8d608662010-08-30 03:02:23 -07002794 default:
2795 orientation = 0;
2796 }
2797
Jeff Brownd41cff22011-03-03 02:09:54 -08002798 // X and Y
2799 // Adjust coords for surface orientation.
2800 float x, y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002801 switch (mLocked.surfaceOrientation) {
Jeff Brownd41cff22011-03-03 02:09:54 -08002802 case DISPLAY_ORIENTATION_90:
2803 x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
2804 y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002805 orientation -= M_PI_2;
2806 if (orientation < - M_PI_2) {
2807 orientation += M_PI;
2808 }
2809 break;
Jeff Brownd41cff22011-03-03 02:09:54 -08002810 case DISPLAY_ORIENTATION_180:
2811 x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
2812 y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002813 break;
Jeff Brownd41cff22011-03-03 02:09:54 -08002814 case DISPLAY_ORIENTATION_270:
2815 x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
2816 y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002817 orientation += M_PI_2;
2818 if (orientation > M_PI_2) {
2819 orientation -= M_PI;
2820 }
2821 break;
Jeff Brownd41cff22011-03-03 02:09:54 -08002822 default:
2823 x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
2824 y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
2825 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002826 }
2827
Jeff Brown8d608662010-08-30 03:02:23 -07002828 // Write output coords.
2829 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002830 out.clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -08002831 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2832 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2833 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2834 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2835 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2836 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2837 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2838 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2839 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002840
Jeff Brown8d608662010-08-30 03:02:23 -07002841 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002842
2843 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002844 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002845 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002846 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002847
2848 // Check edge flags by looking only at the first pointer since the flags are
2849 // global to the event.
2850 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownd41cff22011-03-03 02:09:54 -08002851 uint32_t inIndex = touch->idToIndex[pointerIds[0]];
2852 const PointerData& in = touch->pointers[inIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002853
Jeff Brownd41cff22011-03-03 02:09:54 -08002854 if (in.x <= mRawAxes.x.minValue) {
2855 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
2856 mLocked.surfaceOrientation);
2857 } else if (in.x >= mRawAxes.x.maxValue) {
2858 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
2859 mLocked.surfaceOrientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002860 }
Jeff Brownd41cff22011-03-03 02:09:54 -08002861 if (in.y <= mRawAxes.y.minValue) {
2862 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
2863 mLocked.surfaceOrientation);
2864 } else if (in.y >= mRawAxes.y.maxValue) {
2865 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
2866 mLocked.surfaceOrientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002867 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002868 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002869
2870 xPrecision = mLocked.orientedXPrecision;
2871 yPrecision = mLocked.orientedYPrecision;
2872 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002873
Jeff Brown83c09682010-12-23 17:50:18 -08002874 getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002875 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002876 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002877 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002878}
2879
Jeff Brown6328cdc2010-07-29 18:18:33 -07002880bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brownd41cff22011-03-03 02:09:54 -08002881 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2882 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002883}
2884
Jeff Brown6328cdc2010-07-29 18:18:33 -07002885const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2886 int32_t x, int32_t y) {
2887 size_t numVirtualKeys = mLocked.virtualKeys.size();
2888 for (size_t i = 0; i < numVirtualKeys; i++) {
2889 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002890
2891#if DEBUG_VIRTUAL_KEYS
2892 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2893 "left=%d, top=%d, right=%d, bottom=%d",
2894 x, y,
2895 virtualKey.keyCode, virtualKey.scanCode,
2896 virtualKey.hitLeft, virtualKey.hitTop,
2897 virtualKey.hitRight, virtualKey.hitBottom);
2898#endif
2899
2900 if (virtualKey.isHit(x, y)) {
2901 return & virtualKey;
2902 }
2903 }
2904
2905 return NULL;
2906}
2907
2908void TouchInputMapper::calculatePointerIds() {
2909 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2910 uint32_t lastPointerCount = mLastTouch.pointerCount;
2911
2912 if (currentPointerCount == 0) {
2913 // No pointers to assign.
2914 mCurrentTouch.idBits.clear();
2915 } else if (lastPointerCount == 0) {
2916 // All pointers are new.
2917 mCurrentTouch.idBits.clear();
2918 for (uint32_t i = 0; i < currentPointerCount; i++) {
2919 mCurrentTouch.pointers[i].id = i;
2920 mCurrentTouch.idToIndex[i] = i;
2921 mCurrentTouch.idBits.markBit(i);
2922 }
2923 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
2924 // Only one pointer and no change in count so it must have the same id as before.
2925 uint32_t id = mLastTouch.pointers[0].id;
2926 mCurrentTouch.pointers[0].id = id;
2927 mCurrentTouch.idToIndex[id] = 0;
2928 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
2929 } else {
2930 // General case.
2931 // We build a heap of squared euclidean distances between current and last pointers
2932 // associated with the current and last pointer indices. Then, we find the best
2933 // match (by distance) for each current pointer.
2934 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
2935
2936 uint32_t heapSize = 0;
2937 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
2938 currentPointerIndex++) {
2939 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
2940 lastPointerIndex++) {
2941 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
2942 - mLastTouch.pointers[lastPointerIndex].x;
2943 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
2944 - mLastTouch.pointers[lastPointerIndex].y;
2945
2946 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
2947
2948 // Insert new element into the heap (sift up).
2949 heap[heapSize].currentPointerIndex = currentPointerIndex;
2950 heap[heapSize].lastPointerIndex = lastPointerIndex;
2951 heap[heapSize].distance = distance;
2952 heapSize += 1;
2953 }
2954 }
2955
2956 // Heapify
2957 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
2958 startIndex -= 1;
2959 for (uint32_t parentIndex = startIndex; ;) {
2960 uint32_t childIndex = parentIndex * 2 + 1;
2961 if (childIndex >= heapSize) {
2962 break;
2963 }
2964
2965 if (childIndex + 1 < heapSize
2966 && heap[childIndex + 1].distance < heap[childIndex].distance) {
2967 childIndex += 1;
2968 }
2969
2970 if (heap[parentIndex].distance <= heap[childIndex].distance) {
2971 break;
2972 }
2973
2974 swap(heap[parentIndex], heap[childIndex]);
2975 parentIndex = childIndex;
2976 }
2977 }
2978
2979#if DEBUG_POINTER_ASSIGNMENT
2980 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
2981 for (size_t i = 0; i < heapSize; i++) {
2982 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
2983 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
2984 heap[i].distance);
2985 }
2986#endif
2987
2988 // Pull matches out by increasing order of distance.
2989 // To avoid reassigning pointers that have already been matched, the loop keeps track
2990 // of which last and current pointers have been matched using the matchedXXXBits variables.
2991 // It also tracks the used pointer id bits.
2992 BitSet32 matchedLastBits(0);
2993 BitSet32 matchedCurrentBits(0);
2994 BitSet32 usedIdBits(0);
2995 bool first = true;
2996 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
2997 for (;;) {
2998 if (first) {
2999 // The first time through the loop, we just consume the root element of
3000 // the heap (the one with smallest distance).
3001 first = false;
3002 } else {
3003 // Previous iterations consumed the root element of the heap.
3004 // Pop root element off of the heap (sift down).
3005 heapSize -= 1;
3006 assert(heapSize > 0);
3007
3008 // Sift down.
3009 heap[0] = heap[heapSize];
3010 for (uint32_t parentIndex = 0; ;) {
3011 uint32_t childIndex = parentIndex * 2 + 1;
3012 if (childIndex >= heapSize) {
3013 break;
3014 }
3015
3016 if (childIndex + 1 < heapSize
3017 && heap[childIndex + 1].distance < heap[childIndex].distance) {
3018 childIndex += 1;
3019 }
3020
3021 if (heap[parentIndex].distance <= heap[childIndex].distance) {
3022 break;
3023 }
3024
3025 swap(heap[parentIndex], heap[childIndex]);
3026 parentIndex = childIndex;
3027 }
3028
3029#if DEBUG_POINTER_ASSIGNMENT
3030 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
3031 for (size_t i = 0; i < heapSize; i++) {
3032 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
3033 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
3034 heap[i].distance);
3035 }
3036#endif
3037 }
3038
3039 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
3040 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
3041
3042 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
3043 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
3044
3045 matchedCurrentBits.markBit(currentPointerIndex);
3046 matchedLastBits.markBit(lastPointerIndex);
3047
3048 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
3049 mCurrentTouch.pointers[currentPointerIndex].id = id;
3050 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3051 usedIdBits.markBit(id);
3052
3053#if DEBUG_POINTER_ASSIGNMENT
3054 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
3055 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
3056#endif
3057 break;
3058 }
3059 }
3060
3061 // Assign fresh ids to new pointers.
3062 if (currentPointerCount > lastPointerCount) {
3063 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
3064 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
3065 uint32_t id = usedIdBits.firstUnmarkedBit();
3066
3067 mCurrentTouch.pointers[currentPointerIndex].id = id;
3068 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3069 usedIdBits.markBit(id);
3070
3071#if DEBUG_POINTER_ASSIGNMENT
3072 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
3073 currentPointerIndex, id);
3074#endif
3075
3076 if (--i == 0) break; // done
3077 matchedCurrentBits.markBit(currentPointerIndex);
3078 }
3079 }
3080
3081 // Fix id bits.
3082 mCurrentTouch.idBits = usedIdBits;
3083 }
3084}
3085
3086/* Special hack for devices that have bad screen data: if one of the
3087 * points has moved more than a screen height from the last position,
3088 * then drop it. */
3089bool TouchInputMapper::applyBadTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003090 uint32_t pointerCount = mCurrentTouch.pointerCount;
3091
3092 // Nothing to do if there are no points.
3093 if (pointerCount == 0) {
3094 return false;
3095 }
3096
3097 // Don't do anything if a finger is going down or up. We run
3098 // here before assigning pointer IDs, so there isn't a good
3099 // way to do per-finger matching.
3100 if (pointerCount != mLastTouch.pointerCount) {
3101 return false;
3102 }
3103
3104 // We consider a single movement across more than a 7/16 of
3105 // the long size of the screen to be bad. This was a magic value
3106 // determined by looking at the maximum distance it is feasible
3107 // to actually move in one sample.
Jeff Brownd41cff22011-03-03 02:09:54 -08003108 int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003109
3110 // XXX The original code in InputDevice.java included commented out
3111 // code for testing the X axis. Note that when we drop a point
3112 // we don't actually restore the old X either. Strange.
3113 // The old code also tries to track when bad points were previously
3114 // detected but it turns out that due to the placement of a "break"
3115 // at the end of the loop, we never set mDroppedBadPoint to true
3116 // so it is effectively dead code.
3117 // Need to figure out if the old code is busted or just overcomplicated
3118 // but working as intended.
3119
3120 // Look through all new points and see if any are farther than
3121 // acceptable from all previous points.
3122 for (uint32_t i = pointerCount; i-- > 0; ) {
3123 int32_t y = mCurrentTouch.pointers[i].y;
3124 int32_t closestY = INT_MAX;
3125 int32_t closestDeltaY = 0;
3126
3127#if DEBUG_HACKS
3128 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3129#endif
3130
3131 for (uint32_t j = pointerCount; j-- > 0; ) {
3132 int32_t lastY = mLastTouch.pointers[j].y;
3133 int32_t deltaY = abs(y - lastY);
3134
3135#if DEBUG_HACKS
3136 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3137 j, lastY, deltaY);
3138#endif
3139
3140 if (deltaY < maxDeltaY) {
3141 goto SkipSufficientlyClosePoint;
3142 }
3143 if (deltaY < closestDeltaY) {
3144 closestDeltaY = deltaY;
3145 closestY = lastY;
3146 }
3147 }
3148
3149 // Must not have found a close enough match.
3150#if DEBUG_HACKS
3151 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3152 i, y, closestY, closestDeltaY, maxDeltaY);
3153#endif
3154
3155 mCurrentTouch.pointers[i].y = closestY;
3156 return true; // XXX original code only corrects one point
3157
3158 SkipSufficientlyClosePoint: ;
3159 }
3160
3161 // No change.
3162 return false;
3163}
3164
3165/* Special hack for devices that have bad screen data: drop points where
3166 * the coordinate value for one axis has jumped to the other pointer's location.
3167 */
3168bool TouchInputMapper::applyJumpyTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003169 uint32_t pointerCount = mCurrentTouch.pointerCount;
3170 if (mLastTouch.pointerCount != pointerCount) {
3171#if DEBUG_HACKS
3172 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3173 mLastTouch.pointerCount, pointerCount);
3174 for (uint32_t i = 0; i < pointerCount; i++) {
3175 LOGD(" Pointer %d (%d, %d)", i,
3176 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3177 }
3178#endif
3179
3180 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3181 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3182 // Just drop the first few events going from 1 to 2 pointers.
3183 // They're bad often enough that they're not worth considering.
3184 mCurrentTouch.pointerCount = 1;
3185 mJumpyTouchFilter.jumpyPointsDropped += 1;
3186
3187#if DEBUG_HACKS
3188 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3189#endif
3190 return true;
3191 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3192 // The event when we go from 2 -> 1 tends to be messed up too
3193 mCurrentTouch.pointerCount = 2;
3194 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3195 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3196 mJumpyTouchFilter.jumpyPointsDropped += 1;
3197
3198#if DEBUG_HACKS
3199 for (int32_t i = 0; i < 2; i++) {
3200 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3201 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3202 }
3203#endif
3204 return true;
3205 }
3206 }
3207 // Reset jumpy points dropped on other transitions or if limit exceeded.
3208 mJumpyTouchFilter.jumpyPointsDropped = 0;
3209
3210#if DEBUG_HACKS
3211 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3212#endif
3213 return false;
3214 }
3215
3216 // We have the same number of pointers as last time.
3217 // A 'jumpy' point is one where the coordinate value for one axis
3218 // has jumped to the other pointer's location. No need to do anything
3219 // else if we only have one pointer.
3220 if (pointerCount < 2) {
3221 return false;
3222 }
3223
3224 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brownd41cff22011-03-03 02:09:54 -08003225 int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003226
3227 // We only replace the single worst jumpy point as characterized by pointer distance
3228 // in a single axis.
3229 int32_t badPointerIndex = -1;
3230 int32_t badPointerReplacementIndex = -1;
3231 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3232
3233 for (uint32_t i = pointerCount; i-- > 0; ) {
3234 int32_t x = mCurrentTouch.pointers[i].x;
3235 int32_t y = mCurrentTouch.pointers[i].y;
3236
3237#if DEBUG_HACKS
3238 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3239#endif
3240
3241 // Check if a touch point is too close to another's coordinates
3242 bool dropX = false, dropY = false;
3243 for (uint32_t j = 0; j < pointerCount; j++) {
3244 if (i == j) {
3245 continue;
3246 }
3247
3248 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3249 dropX = true;
3250 break;
3251 }
3252
3253 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3254 dropY = true;
3255 break;
3256 }
3257 }
3258 if (! dropX && ! dropY) {
3259 continue; // not jumpy
3260 }
3261
3262 // Find a replacement candidate by comparing with older points on the
3263 // complementary (non-jumpy) axis.
3264 int32_t distance = INT_MIN; // distance to be corrected
3265 int32_t replacementIndex = -1;
3266
3267 if (dropX) {
3268 // X looks too close. Find an older replacement point with a close Y.
3269 int32_t smallestDeltaY = INT_MAX;
3270 for (uint32_t j = 0; j < pointerCount; j++) {
3271 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3272 if (deltaY < smallestDeltaY) {
3273 smallestDeltaY = deltaY;
3274 replacementIndex = j;
3275 }
3276 }
3277 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3278 } else {
3279 // Y looks too close. Find an older replacement point with a close X.
3280 int32_t smallestDeltaX = INT_MAX;
3281 for (uint32_t j = 0; j < pointerCount; j++) {
3282 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3283 if (deltaX < smallestDeltaX) {
3284 smallestDeltaX = deltaX;
3285 replacementIndex = j;
3286 }
3287 }
3288 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3289 }
3290
3291 // If replacing this pointer would correct a worse error than the previous ones
3292 // considered, then use this replacement instead.
3293 if (distance > badPointerDistance) {
3294 badPointerIndex = i;
3295 badPointerReplacementIndex = replacementIndex;
3296 badPointerDistance = distance;
3297 }
3298 }
3299
3300 // Correct the jumpy pointer if one was found.
3301 if (badPointerIndex >= 0) {
3302#if DEBUG_HACKS
3303 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3304 badPointerIndex,
3305 mLastTouch.pointers[badPointerReplacementIndex].x,
3306 mLastTouch.pointers[badPointerReplacementIndex].y);
3307#endif
3308
3309 mCurrentTouch.pointers[badPointerIndex].x =
3310 mLastTouch.pointers[badPointerReplacementIndex].x;
3311 mCurrentTouch.pointers[badPointerIndex].y =
3312 mLastTouch.pointers[badPointerReplacementIndex].y;
3313 mJumpyTouchFilter.jumpyPointsDropped += 1;
3314 return true;
3315 }
3316 }
3317
3318 mJumpyTouchFilter.jumpyPointsDropped = 0;
3319 return false;
3320}
3321
3322/* Special hack for devices that have bad screen data: aggregate and
3323 * compute averages of the coordinate data, to reduce the amount of
3324 * jitter seen by applications. */
3325void TouchInputMapper::applyAveragingTouchFilter() {
3326 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3327 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3328 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3329 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003330 int32_t pressure;
3331 switch (mCalibration.pressureSource) {
3332 case Calibration::PRESSURE_SOURCE_PRESSURE:
3333 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3334 break;
3335 case Calibration::PRESSURE_SOURCE_TOUCH:
3336 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3337 break;
3338 default:
3339 pressure = 1;
3340 break;
3341 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003342
3343 if (mLastTouch.idBits.hasBit(id)) {
3344 // Pointer was down before and is still down now.
3345 // Compute average over history trace.
3346 uint32_t start = mAveragingTouchFilter.historyStart[id];
3347 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3348
3349 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3350 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3351 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3352
3353#if DEBUG_HACKS
3354 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3355 id, distance);
3356#endif
3357
3358 if (distance < AVERAGING_DISTANCE_LIMIT) {
3359 // Increment end index in preparation for recording new historical data.
3360 end += 1;
3361 if (end > AVERAGING_HISTORY_SIZE) {
3362 end = 0;
3363 }
3364
3365 // If the end index has looped back to the start index then we have filled
3366 // the historical trace up to the desired size so we drop the historical
3367 // data at the start of the trace.
3368 if (end == start) {
3369 start += 1;
3370 if (start > AVERAGING_HISTORY_SIZE) {
3371 start = 0;
3372 }
3373 }
3374
3375 // Add the raw data to the historical trace.
3376 mAveragingTouchFilter.historyStart[id] = start;
3377 mAveragingTouchFilter.historyEnd[id] = end;
3378 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3379 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3380 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3381
3382 // Average over all historical positions in the trace by total pressure.
3383 int32_t averagedX = 0;
3384 int32_t averagedY = 0;
3385 int32_t totalPressure = 0;
3386 for (;;) {
3387 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3388 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3389 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3390 .pointers[id].pressure;
3391
3392 averagedX += historicalX * historicalPressure;
3393 averagedY += historicalY * historicalPressure;
3394 totalPressure += historicalPressure;
3395
3396 if (start == end) {
3397 break;
3398 }
3399
3400 start += 1;
3401 if (start > AVERAGING_HISTORY_SIZE) {
3402 start = 0;
3403 }
3404 }
3405
Jeff Brown8d608662010-08-30 03:02:23 -07003406 if (totalPressure != 0) {
3407 averagedX /= totalPressure;
3408 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003409
3410#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003411 LOGD("AveragingTouchFilter: Pointer id %d - "
3412 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3413 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003414#endif
3415
Jeff Brown8d608662010-08-30 03:02:23 -07003416 mCurrentTouch.pointers[currentIndex].x = averagedX;
3417 mCurrentTouch.pointers[currentIndex].y = averagedY;
3418 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003419 } else {
3420#if DEBUG_HACKS
3421 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3422#endif
3423 }
3424 } else {
3425#if DEBUG_HACKS
3426 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3427#endif
3428 }
3429
3430 // Reset pointer history.
3431 mAveragingTouchFilter.historyStart[id] = 0;
3432 mAveragingTouchFilter.historyEnd[id] = 0;
3433 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3434 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3435 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3436 }
3437}
3438
3439int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003440 { // acquire lock
3441 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003442
Jeff Brown6328cdc2010-07-29 18:18:33 -07003443 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003444 return AKEY_STATE_VIRTUAL;
3445 }
3446
Jeff Brown6328cdc2010-07-29 18:18:33 -07003447 size_t numVirtualKeys = mLocked.virtualKeys.size();
3448 for (size_t i = 0; i < numVirtualKeys; i++) {
3449 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003450 if (virtualKey.keyCode == keyCode) {
3451 return AKEY_STATE_UP;
3452 }
3453 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003454 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003455
3456 return AKEY_STATE_UNKNOWN;
3457}
3458
3459int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003460 { // acquire lock
3461 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003462
Jeff Brown6328cdc2010-07-29 18:18:33 -07003463 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003464 return AKEY_STATE_VIRTUAL;
3465 }
3466
Jeff Brown6328cdc2010-07-29 18:18:33 -07003467 size_t numVirtualKeys = mLocked.virtualKeys.size();
3468 for (size_t i = 0; i < numVirtualKeys; i++) {
3469 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003470 if (virtualKey.scanCode == scanCode) {
3471 return AKEY_STATE_UP;
3472 }
3473 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003474 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003475
3476 return AKEY_STATE_UNKNOWN;
3477}
3478
3479bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3480 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003481 { // acquire lock
3482 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003483
Jeff Brown6328cdc2010-07-29 18:18:33 -07003484 size_t numVirtualKeys = mLocked.virtualKeys.size();
3485 for (size_t i = 0; i < numVirtualKeys; i++) {
3486 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003487
3488 for (size_t i = 0; i < numCodes; i++) {
3489 if (virtualKey.keyCode == keyCodes[i]) {
3490 outFlags[i] = 1;
3491 }
3492 }
3493 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003494 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003495
3496 return true;
3497}
3498
3499
3500// --- SingleTouchInputMapper ---
3501
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003502SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3503 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003504 initialize();
3505}
3506
3507SingleTouchInputMapper::~SingleTouchInputMapper() {
3508}
3509
3510void SingleTouchInputMapper::initialize() {
3511 mAccumulator.clear();
3512
3513 mDown = false;
3514 mX = 0;
3515 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003516 mPressure = 0; // default to 0 for devices that don't report pressure
3517 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003518}
3519
3520void SingleTouchInputMapper::reset() {
3521 TouchInputMapper::reset();
3522
Jeff Brown6d0fec22010-07-23 21:28:06 -07003523 initialize();
3524 }
3525
3526void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3527 switch (rawEvent->type) {
3528 case EV_KEY:
3529 switch (rawEvent->scanCode) {
3530 case BTN_TOUCH:
3531 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3532 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003533 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3534 // not have received valid position information yet. This logic assumes that
3535 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003536 break;
3537 }
3538 break;
3539
3540 case EV_ABS:
3541 switch (rawEvent->scanCode) {
3542 case ABS_X:
3543 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3544 mAccumulator.absX = rawEvent->value;
3545 break;
3546 case ABS_Y:
3547 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3548 mAccumulator.absY = rawEvent->value;
3549 break;
3550 case ABS_PRESSURE:
3551 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3552 mAccumulator.absPressure = rawEvent->value;
3553 break;
3554 case ABS_TOOL_WIDTH:
3555 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3556 mAccumulator.absToolWidth = rawEvent->value;
3557 break;
3558 }
3559 break;
3560
3561 case EV_SYN:
3562 switch (rawEvent->scanCode) {
3563 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003564 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003565 break;
3566 }
3567 break;
3568 }
3569}
3570
3571void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003572 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003573 if (fields == 0) {
3574 return; // no new state changes, so nothing to do
3575 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003576
3577 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3578 mDown = mAccumulator.btnTouch;
3579 }
3580
3581 if (fields & Accumulator::FIELD_ABS_X) {
3582 mX = mAccumulator.absX;
3583 }
3584
3585 if (fields & Accumulator::FIELD_ABS_Y) {
3586 mY = mAccumulator.absY;
3587 }
3588
3589 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3590 mPressure = mAccumulator.absPressure;
3591 }
3592
3593 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003594 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003595 }
3596
3597 mCurrentTouch.clear();
3598
3599 if (mDown) {
3600 mCurrentTouch.pointerCount = 1;
3601 mCurrentTouch.pointers[0].id = 0;
3602 mCurrentTouch.pointers[0].x = mX;
3603 mCurrentTouch.pointers[0].y = mY;
3604 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003605 mCurrentTouch.pointers[0].touchMajor = 0;
3606 mCurrentTouch.pointers[0].touchMinor = 0;
3607 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3608 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003609 mCurrentTouch.pointers[0].orientation = 0;
3610 mCurrentTouch.idToIndex[0] = 0;
3611 mCurrentTouch.idBits.markBit(0);
3612 }
3613
3614 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003615
3616 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003617}
3618
Jeff Brown8d608662010-08-30 03:02:23 -07003619void SingleTouchInputMapper::configureRawAxes() {
3620 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003621
Jeff Brown8d608662010-08-30 03:02:23 -07003622 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3623 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3624 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3625 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003626}
3627
3628
3629// --- MultiTouchInputMapper ---
3630
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003631MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3632 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003633 initialize();
3634}
3635
3636MultiTouchInputMapper::~MultiTouchInputMapper() {
3637}
3638
3639void MultiTouchInputMapper::initialize() {
3640 mAccumulator.clear();
3641}
3642
3643void MultiTouchInputMapper::reset() {
3644 TouchInputMapper::reset();
3645
Jeff Brown6d0fec22010-07-23 21:28:06 -07003646 initialize();
3647}
3648
3649void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3650 switch (rawEvent->type) {
3651 case EV_ABS: {
3652 uint32_t pointerIndex = mAccumulator.pointerCount;
3653 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3654
3655 switch (rawEvent->scanCode) {
3656 case ABS_MT_POSITION_X:
3657 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3658 pointer->absMTPositionX = rawEvent->value;
3659 break;
3660 case ABS_MT_POSITION_Y:
3661 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3662 pointer->absMTPositionY = rawEvent->value;
3663 break;
3664 case ABS_MT_TOUCH_MAJOR:
3665 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3666 pointer->absMTTouchMajor = rawEvent->value;
3667 break;
3668 case ABS_MT_TOUCH_MINOR:
3669 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3670 pointer->absMTTouchMinor = rawEvent->value;
3671 break;
3672 case ABS_MT_WIDTH_MAJOR:
3673 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3674 pointer->absMTWidthMajor = rawEvent->value;
3675 break;
3676 case ABS_MT_WIDTH_MINOR:
3677 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3678 pointer->absMTWidthMinor = rawEvent->value;
3679 break;
3680 case ABS_MT_ORIENTATION:
3681 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3682 pointer->absMTOrientation = rawEvent->value;
3683 break;
3684 case ABS_MT_TRACKING_ID:
3685 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3686 pointer->absMTTrackingId = rawEvent->value;
3687 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003688 case ABS_MT_PRESSURE:
3689 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3690 pointer->absMTPressure = rawEvent->value;
3691 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003692 }
3693 break;
3694 }
3695
3696 case EV_SYN:
3697 switch (rawEvent->scanCode) {
3698 case SYN_MT_REPORT: {
3699 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3700 uint32_t pointerIndex = mAccumulator.pointerCount;
3701
3702 if (mAccumulator.pointers[pointerIndex].fields) {
3703 if (pointerIndex == MAX_POINTERS) {
3704 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3705 MAX_POINTERS);
3706 } else {
3707 pointerIndex += 1;
3708 mAccumulator.pointerCount = pointerIndex;
3709 }
3710 }
3711
3712 mAccumulator.pointers[pointerIndex].clear();
3713 break;
3714 }
3715
3716 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003717 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003718 break;
3719 }
3720 break;
3721 }
3722}
3723
3724void MultiTouchInputMapper::sync(nsecs_t when) {
3725 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003726 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003727
Jeff Brown6d0fec22010-07-23 21:28:06 -07003728 uint32_t inCount = mAccumulator.pointerCount;
3729 uint32_t outCount = 0;
3730 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003731
Jeff Brown6d0fec22010-07-23 21:28:06 -07003732 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003733
Jeff Brown6d0fec22010-07-23 21:28:06 -07003734 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003735 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3736 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003737
Jeff Brown6d0fec22010-07-23 21:28:06 -07003738 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003739 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3740 // Drop this finger.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003741 continue;
3742 }
3743
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003744 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3745 outPointer.x = inPointer.absMTPositionX;
3746 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003747
Jeff Brown8d608662010-08-30 03:02:23 -07003748 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3749 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003750 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3751 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003752 continue;
3753 }
Jeff Brown8d608662010-08-30 03:02:23 -07003754 outPointer.pressure = inPointer.absMTPressure;
3755 } else {
3756 // Default pressure to 0 if absent.
3757 outPointer.pressure = 0;
3758 }
3759
3760 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3761 if (inPointer.absMTTouchMajor <= 0) {
3762 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3763 // a pointer going up. Drop this finger.
3764 continue;
3765 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003766 outPointer.touchMajor = inPointer.absMTTouchMajor;
3767 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003768 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003769 outPointer.touchMajor = 0;
3770 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003771
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003772 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3773 outPointer.touchMinor = inPointer.absMTTouchMinor;
3774 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003775 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003776 outPointer.touchMinor = outPointer.touchMajor;
3777 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003778
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003779 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3780 outPointer.toolMajor = inPointer.absMTWidthMajor;
3781 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003782 // Default tool area to 0 if absent.
3783 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003784 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003785
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003786 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3787 outPointer.toolMinor = inPointer.absMTWidthMinor;
3788 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003789 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003790 outPointer.toolMinor = outPointer.toolMajor;
3791 }
3792
3793 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3794 outPointer.orientation = inPointer.absMTOrientation;
3795 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003796 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003797 outPointer.orientation = 0;
3798 }
3799
Jeff Brown8d608662010-08-30 03:02:23 -07003800 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003801 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003802 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3803 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003804
Jeff Brown6d0fec22010-07-23 21:28:06 -07003805 if (id > MAX_POINTER_ID) {
3806#if DEBUG_POINTERS
3807 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003808 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003809 id, MAX_POINTER_ID);
3810#endif
3811 havePointerIds = false;
3812 }
3813 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003814 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003815 mCurrentTouch.idToIndex[id] = outCount;
3816 mCurrentTouch.idBits.markBit(id);
3817 }
3818 } else {
3819 havePointerIds = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003820 }
3821 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003822
Jeff Brown6d0fec22010-07-23 21:28:06 -07003823 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003824 }
3825
Jeff Brown6d0fec22010-07-23 21:28:06 -07003826 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003827
Jeff Brown6d0fec22010-07-23 21:28:06 -07003828 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003829
3830 mAccumulator.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003831}
3832
Jeff Brown8d608662010-08-30 03:02:23 -07003833void MultiTouchInputMapper::configureRawAxes() {
3834 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003835
Jeff Brown8d608662010-08-30 03:02:23 -07003836 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3837 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3838 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3839 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3840 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3841 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3842 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3843 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003844}
3845
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003846
Jeff Browncb1404e2011-01-15 18:14:15 -08003847// --- JoystickInputMapper ---
3848
3849JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3850 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08003851}
3852
3853JoystickInputMapper::~JoystickInputMapper() {
3854}
3855
3856uint32_t JoystickInputMapper::getSources() {
3857 return AINPUT_SOURCE_JOYSTICK;
3858}
3859
3860void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3861 InputMapper::populateDeviceInfo(info);
3862
Jeff Brown6f2fba42011-02-19 01:08:02 -08003863 for (size_t i = 0; i < mAxes.size(); i++) {
3864 const Axis& axis = mAxes.valueAt(i);
3865 info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003866 }
3867}
3868
3869void JoystickInputMapper::dump(String8& dump) {
3870 dump.append(INDENT2 "Joystick Input Mapper:\n");
3871
Jeff Brown6f2fba42011-02-19 01:08:02 -08003872 dump.append(INDENT3 "Axes:\n");
3873 size_t numAxes = mAxes.size();
3874 for (size_t i = 0; i < numAxes; i++) {
3875 const Axis& axis = mAxes.valueAt(i);
3876 const char* label = getAxisLabel(axis.axis);
3877 char name[32];
3878 if (label) {
3879 strncpy(name, label, sizeof(name));
3880 name[sizeof(name) - 1] = '\0';
3881 } else {
3882 snprintf(name, sizeof(name), "%d", axis.axis);
3883 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003884 dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
Jeff Brown6f2fba42011-02-19 01:08:02 -08003885 "scale=%0.3f, offset=%0.3f\n",
Jeff Browncb1404e2011-01-15 18:14:15 -08003886 name, axis.min, axis.max, axis.flat, axis.fuzz,
Jeff Brown6f2fba42011-02-19 01:08:02 -08003887 axis.scale, axis.offset);
3888 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3889 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3890 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003891 }
3892}
3893
3894void JoystickInputMapper::configure() {
3895 InputMapper::configure();
3896
Jeff Brown6f2fba42011-02-19 01:08:02 -08003897 // Collect all axes.
3898 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3899 RawAbsoluteAxisInfo rawAxisInfo;
3900 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3901 if (rawAxisInfo.valid) {
3902 int32_t axisId;
3903 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
3904 if (!explicitlyMapped) {
3905 // Axis is not explicitly mapped, will choose a generic axis later.
3906 axisId = -1;
3907 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003908
Jeff Brown6f2fba42011-02-19 01:08:02 -08003909 Axis axis;
3910 if (isCenteredAxis(axisId)) {
3911 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3912 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
3913 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3914 scale, offset, -1.0f, 1.0f,
3915 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3916 } else {
3917 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
3918 axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
3919 scale, 0.0f, 0.0f, 1.0f,
3920 rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
3921 }
3922
3923 // To eliminate noise while the joystick is at rest, filter out small variations
3924 // in axis values up front.
3925 axis.filter = axis.flat * 0.25f;
3926
3927 mAxes.add(abs, axis);
3928 }
3929 }
3930
3931 // If there are too many axes, start dropping them.
3932 // Prefer to keep explicitly mapped axes.
3933 if (mAxes.size() > PointerCoords::MAX_AXES) {
3934 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
3935 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
3936 pruneAxes(true);
3937 pruneAxes(false);
3938 }
3939
3940 // Assign generic axis ids to remaining axes.
3941 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
3942 size_t numAxes = mAxes.size();
3943 for (size_t i = 0; i < numAxes; i++) {
3944 Axis& axis = mAxes.editValueAt(i);
3945 if (axis.axis < 0) {
3946 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
3947 && haveAxis(nextGenericAxisId)) {
3948 nextGenericAxisId += 1;
3949 }
3950
3951 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
3952 axis.axis = nextGenericAxisId;
3953 nextGenericAxisId += 1;
3954 } else {
3955 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
3956 "have already been assigned to other axes.",
3957 getDeviceName().string(), mAxes.keyAt(i));
3958 mAxes.removeItemsAt(i--);
3959 numAxes -= 1;
3960 }
3961 }
3962 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003963}
3964
Jeff Brown6f2fba42011-02-19 01:08:02 -08003965bool JoystickInputMapper::haveAxis(int32_t axis) {
3966 size_t numAxes = mAxes.size();
3967 for (size_t i = 0; i < numAxes; i++) {
3968 if (mAxes.valueAt(i).axis == axis) {
3969 return true;
3970 }
3971 }
3972 return false;
3973}
Jeff Browncb1404e2011-01-15 18:14:15 -08003974
Jeff Brown6f2fba42011-02-19 01:08:02 -08003975void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
3976 size_t i = mAxes.size();
3977 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
3978 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
3979 continue;
3980 }
3981 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
3982 getDeviceName().string(), mAxes.keyAt(i));
3983 mAxes.removeItemsAt(i);
3984 }
3985}
3986
3987bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
3988 switch (axis) {
3989 case AMOTION_EVENT_AXIS_X:
3990 case AMOTION_EVENT_AXIS_Y:
3991 case AMOTION_EVENT_AXIS_Z:
3992 case AMOTION_EVENT_AXIS_RX:
3993 case AMOTION_EVENT_AXIS_RY:
3994 case AMOTION_EVENT_AXIS_RZ:
3995 case AMOTION_EVENT_AXIS_HAT_X:
3996 case AMOTION_EVENT_AXIS_HAT_Y:
3997 case AMOTION_EVENT_AXIS_ORIENTATION:
3998 return true;
3999 default:
4000 return false;
4001 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004002}
4003
4004void JoystickInputMapper::reset() {
4005 // Recenter all axes.
4006 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08004007
Jeff Brown6f2fba42011-02-19 01:08:02 -08004008 size_t numAxes = mAxes.size();
4009 for (size_t i = 0; i < numAxes; i++) {
4010 Axis& axis = mAxes.editValueAt(i);
4011 axis.newValue = 0;
4012 }
4013
4014 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08004015
4016 InputMapper::reset();
4017}
4018
4019void JoystickInputMapper::process(const RawEvent* rawEvent) {
4020 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004021 case EV_ABS: {
4022 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
4023 if (index >= 0) {
4024 Axis& axis = mAxes.editValueAt(index);
4025 float newValue = rawEvent->value * axis.scale + axis.offset;
4026 if (newValue != axis.newValue) {
4027 axis.newValue = newValue;
4028 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004029 }
4030 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004031 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004032
4033 case EV_SYN:
4034 switch (rawEvent->scanCode) {
4035 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08004036 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08004037 break;
4038 }
4039 break;
4040 }
4041}
4042
Jeff Brown6f2fba42011-02-19 01:08:02 -08004043void JoystickInputMapper::sync(nsecs_t when, bool force) {
4044 if (!force && !haveAxesChangedSignificantly()) {
4045 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08004046 }
4047
4048 int32_t metaState = mContext->getGlobalMetaState();
4049
Jeff Brown6f2fba42011-02-19 01:08:02 -08004050 PointerCoords pointerCoords;
4051 pointerCoords.clear();
4052
4053 size_t numAxes = mAxes.size();
4054 for (size_t i = 0; i < numAxes; i++) {
4055 Axis& axis = mAxes.editValueAt(i);
4056 pointerCoords.setAxisValue(axis.axis, axis.newValue);
4057 axis.oldValue = axis.newValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08004058 }
4059
Jeff Brown56194eb2011-03-02 19:23:13 -08004060 // Moving a joystick axis should not wake the devide because joysticks can
4061 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
4062 // button will likely wake the device.
4063 // TODO: Use the input device configuration to control this behavior more finely.
4064 uint32_t policyFlags = 0;
4065
Jeff Brown6f2fba42011-02-19 01:08:02 -08004066 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08004067 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brown6f2fba42011-02-19 01:08:02 -08004068 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
4069 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08004070}
4071
Jeff Brown6f2fba42011-02-19 01:08:02 -08004072bool JoystickInputMapper::haveAxesChangedSignificantly() {
4073 size_t numAxes = mAxes.size();
4074 for (size_t i = 0; i < numAxes; i++) {
4075 const Axis& axis = mAxes.valueAt(i);
4076 if (axis.newValue != axis.oldValue
4077 && fabs(axis.newValue - axis.oldValue) > axis.filter) {
4078 return true;
4079 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004080 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08004081 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08004082}
4083
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004084} // namespace android